[Gatsby][GraphQL]:从另一个查询中检索过滤器参数后运行查询
Posted
技术标签:
【中文标题】[Gatsby][GraphQL]:从另一个查询中检索过滤器参数后运行查询【英文标题】:[Gatsby][GraphQL]: running a query after retrieving filter parameters from another query 【发布时间】:2021-02-08 18:25:59 【问题描述】:快速背景:
我有一个针对大约 40 个城市和 16 个地区的列表项目。我正在以编程方式为每个城市创建一个搜索结果页面:
example.com/london、example.com/paris 等...然后,我需要每个城市页面都有一个查询来检索仅与该城市相关的列表。
到目前为止,我在每个搜索页面上查询相同的列表,然后在组件中过滤客户端上的结果。该解决方案的问题在于,我在每个页面上都使用我不需要的 page-data.json 加载了数千个列表。
我预计列表不会超过数千,这就是为什么我不想添加 apollo 以直接从客户端查询。我希望所有页面都是 s-s-r'd。页面加载后,结果过滤和分页将通过组件和结果数组过滤来完成。
我想象的方式是:
-
运行查询以检索城市列表
对于检索到的每个城市,使用 cityId 作为过滤器参数运行实际页面查询。出于性能目的,我希望在 gatsby-node.js 中发生这种情况,而不是将 cityId 传递给 pageContext,然后从 page.js 运行 pageQuery(由于某种原因,我也无法使其工作)李>
这是我的 gatsby-node.js
const path = require('path')
function slugify(str)
str = str.replace(/^\s+|\s+$/g, ''); // trim
str = str.toLowerCase();
// remove accents, swap ñ for n, etc
var from = "ãàáäâąęẽèéëêćìíïîõòóöôùúüûñńçłśżź·/_,:;";
var to = "aaaaaaeeeeeeciiiiooooouuuunnclszz------";
for (var i=0, l=from.length ; i<l ; i++)
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
.replace(/\s+/g, '-') // collapse whitespace and replace by -
.replace(/-+/g, '-'); // collapse dashes
return str;
;
exports.createPages = async ( graphql, actions ) =>
const createPage = actions;
const listingQueryResults = await graphql(`
query
allDatoCmsListing
nodes
company
cities
cityName
region
regionName
companyName
address
logo
fixed(imgixParams: w: "128", h: "128", fit: "fillmax")
src
#Companywide Terms
insurancePolicy
otherInsuranceTerms
pricePerKm
minAge
deposit
bookingPhoneNumber
displayPhoneNumber
bookingEmail
featuredInCountry
monthlyPrice
listingTitle
pricesIncludeVat
id
originalId
featuredImage
fluid(imgixParams: fit: "crop", w: "800", h: "600", crop: "focalpoint")
aspectRatio
base64
height
sizes
src
srcSet
tracedSVG
width
originalId
gallery
fluid
width
tracedSVG
srcSet
src
sizes
height
base64
aspectRatio
featuredInCity
featuredInRegion
listingDescription
make
makeName
spec
seats
topSpeed
transmission
transmissionType
weekendLimit
weekendNoDepositPrice
weekendPrice
weeklyLimit
weeklyNoDepositPrice
weeklyPrice
acceleration
collectionDropoff
color
colorName
colorValue
dailyLimit
dailyNoDepositPrice
dailyPrice
doors
engine
engineType
engineSize
horsepower
monthlyLimit
monthlyNoDepositPrice
noDepositPricingAvailable
#Listing Terms
applyCompanywideTerms
insurancePolicy
otherInsuranceTerms
pricePerKm
minAge
deposit
listingApproved
`);
const listingTemplate = path.resolve(`src/templates/listing.js`);
listingQueryResults.data.allDatoCmsListing.nodes.forEach(node =>
createPage(
path: `/oferta/$node.originalId-$slugify(node.listingTitle)`,
component: listingTemplate,
context:
listing: node
);
);
const queryResults = await graphql(`
query
allDatoCmsCity
nodes
cityName
cityCase
id
allDatoCmsRegion
nodes
regionName
regionCase
id
`);
const searchTemplate = path.resolve(`src/templates/search.js`);
queryResults.data.allDatoCmsCity.nodes.forEach(node =>
createPage(
path: `/$slugify(node.cityName)`,
component: searchTemplate,
context:
search: node,
);
);
queryResults.data.allDatoCmsRegion.nodes.forEach(node =>
createPage(
path: `/$slugify(node.regionName)`,
component: searchTemplate,
context:
search: node
)
)
const emptySearch =
cityName: null,
regionName: null
createPage(
path: `/cala-polska`,
component: searchTemplate,
context:
search: emptySearch
)
;
我想更精确的问题是:
-
实现上述目标的最佳方法是什么。即获取所有城市和地区
循环遍历城市和地区并分别查询每个城市和地区,而不是运行完全相同的查询并在特定城市/地区页面上获取所有城市/地区的结果?
【问题讨论】:
【参考方案1】:所以我在这上面花了几个小时。我找到了一个对我有用的解决方案。从 5 页查询/秒增加到数百个。那是因为我对所有城市、地区和列表只查询一次。
然后我写了一个过滤函数,它只是一个链
FilterResults = (arr, params) => (
arr.filter(/* city filter / if filter is null -> return true and move to the next*/)
.filter(/*region filter - same as city */)
)
该函数返回列表数组。
我们循环城市结果如下:
query.allDatoCmsCity.nodes.forEach(node =>
params =
city: node.id
results = FilterResults(query.allDatoCmsListing.nodes, params)
// Then our typical gatsby create page
createPage(
path: `/$slugify(node.cityName)`,
component: searchTemplate,
context:
search: node,
listings: results
);
)
这使我们对所有列表只查询一次,而不是对所有列表查询 56 次(因为我在模板中使用了页面查询,这实际上会在每个 createPage 上调用)
这段代码不仅更简洁,而且性能也更高。希望我能像帮助自己一样帮助别人;)
【讨论】:
以上是关于[Gatsby][GraphQL]:从另一个查询中检索过滤器参数后运行查询的主要内容,如果未能解决你的问题,请参考以下文章
Gatsby & GraphQL - 从查询文件中呈现下载链接
来自 markdown 帖子的 Gatsby 图像未从 graphql 查询中显示