[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]:从另一个查询中检索过滤器参数后运行查询的主要内容,如果未能解决你的问题,请参考以下文章

单个 GraphQL 查询中的多个源 (Gatsby)

Gatsby & GraphQL - 从查询文件中呈现下载链接

Gatsby 和 GraphQL - 如何在查询中过滤数组

来自 markdown 帖子的 Gatsby 图像未从 graphql 查询中显示

Gatsby 查询在 graphql 编辑器中有效,但在反应代码中无效

gatsby-source-drupal 不显示 graphql 查询