快速背景:
我有一个针对40个城市和16个地区的列表项目。我正在以编程方式为每个城市创建搜索结果页面:
example.com/london, example.com/paris etc...然后,我需要每个城市页面都有一个查询以检索仅与该城市相关的列表。
到目前为止,我在每个搜索页面上查询相同的列表,然后在组件中过滤客户端上的结果。该解决方案的问题在于,我在每个页面上都加载了不需要的page-data.json列表。
我不希望列表超过数千个,这就是为什么我不想添加apollo直接从客户端查询的原因。我希望所有页面都被替换。页面加载后,结果和分页的过滤将通过组件和结果数组的过滤完成。
我想象的是:
这是我的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
}
})
};
我猜更精确的问题是:
答案 0 :(得分:0)
所以我已经花了几个小时了。我找到了一个对我有用的解决方案。从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都会调用该页面查询)
这不仅是更简洁的代码,而且性能更高。希望我能像我自己一样帮助别人;)