【问题标题】:Elasticsearch searching and sorting across 2 models跨 2 个模型的 Elasticsearch 搜索和排序
【发布时间】:2016-04-29 22:02:30
【问题描述】:

我有 2 个模型:ProductsSkus,其中一个 Product 有一个或多个 Skus,而一个 Sku 恰好属于一个 Product。它们具有以下列:

Product: id, title, content, category_id
Sku:     id, product_id, price

我希望能够在各种搜索和排序配置中每页显示 48 个产品,但我无法将其转换为 elasticsearch。

例如,我不清楚如何在title 上搜索,同时按每个Product 的最低价格Sku 对相关结果进行排序。我尝试了一些不同的方法,最接近的是将所有内容索引为属于Sku,然后像这样搜索:

size: '48',
aggs: { 
  group_by_product: { 
    terms: { field: 'product_id' } 
  }
},
filter: { 
  and: [{
    bool: { 
      must: { range: { price: { gte: 0, lte: 50 } } }
    },{
    bool: { 
      must: { terms: { category_id: [ 1, 2, 3, 4, 5, 6 ] } }
    }
  }]
},
query: {
  fuzzy_like_this: {
    fields: [ 'title', 'content' ],
    like_text: 'Chair',
    fuzziness: 1 
  }
}

但这给出了 48 个匹配的Skus,其中许多属于同一个Product,所以如果我在搜索后尝试将它们组合起来,我的分页就会关闭。

处理这个用例的最佳方法是什么?

更新

尝试使用嵌套方法,使用以下结构:

{ 
  size: '48',
  query:
    { bool:
      { should:
        { fuzzy_like_this: 
          { fields: [ 'title' ],
            like_text: 'chair',
            fuzziness: 1 },
      },
      { must: 
        { nested: 
          { path: 'skus',
            query: 
              { bool: 
                { must: { range: { price: { gte: 0, lte: 100 } } }
              } 
          } 
        }
      } 
    } 
  } 
},
sort: 
  { _score: 'asc',
    'skus.price': 
      { nested_path: 'skus',
        nested_filter: 
          { range: { 'skus.price': { gte: 0, lte: 100 } } },
        order: 'asc',
        mode: 'min' 
      } 
  } 
}

这可能更接近,但仍不确定如何格式化。以上给出了按价格排序的产品,但似乎完全忽略了搜索字段。

【问题讨论】:

  • 将产品包含在sku中的做法是正确的。我认为可以改进的是聚合部分。您实际需要的是 48 个桶的数量,而不是文档的数量。因为桶代表产品。关于分页,用于聚合this is not possible atm.
  • 您是否尝试过nested sku 为nested 的对象?
  • @AndreiStefan 是的,我尝试过在产品下嵌套 skus,但无法通过这种方式找出正确的价格排序。如果桶分页是不可能的,那么它似乎会排除聚合方法?
  • 有点,是的。您对nested 和价格排序有什么问题?
  • 我无法在搜索结果中对其进行排序。即我可以得到按 Product 模型上的相关性搜索排序并在 Sku 模型上按价格过滤的结果,但不能得到按价格排序的搜索结果。

标签: elasticsearch


【解决方案1】:

由于paginating aggregation results is not possible,尽管在product 中包含sku 是一种不错的方法,但我会根据查询的要求使用nested 对象。

作为示例查询:

GET /product/test/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": {
              "query": "whatever",
              "fuzziness": 1,
              "prefix_length": 3
            }
          }
        },
        {
          "nested": {
            "path": "skus",
            "query": {
              "range": {
                "skus.price": {
                  "gte": 11,
                  "lte": 50
                }
              }
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "skus.price": {
        "nested_path": "skus",
        "order": "asc",
        "mode": "min"
      }
    }
  ]
}

【讨论】:

  • 谢谢,我现在正在尝试,会告诉你进展如何
  • 仍然无法正常工作。我在标题上使用模糊搜索,所以请从问题中查看我更新的代码,看看你是否可以发现如何修复查询。
  • 在您更新的查询中,您需要有“skus.price”,因为它是一个嵌套过滤器。
  • 这样的:{ must: { range: { skus.price: { gte: 0, lte: 100 } } }
  • 我做了,类似的东西。我正在使用sort: { 'skus.price': { nested_path: 'skus', mode: 'min', order: 'asc' } } 而不是上面的那种,我在must 数组中也有match: { title: { query: 'whatever', fuzziness: 1, prefix_length: 3 }(没有should 数组)。如果您可以将这些更改添加到您的答案中,我会将其标记为正确。谢谢!
猜你喜欢
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-16
  • 2011-01-03
  • 2023-03-13
  • 1970-01-01
相关资源
最近更新 更多