我正在制作基于 ElasticSearch 的电子商务产品目录的原型(prototype)。 每个产品都被索引为一个文档(其中包含名称和描述等属性)。
有一件事我无法解决,我想根据用户的购买历史提高某些产品的分数。
我能想到的唯一选择是将购买历史存储为产品的子文档。然后将 custom_filters_score 与过滤器一起使用,以查找具有给定 userId 的子文档。在这种情况下,过滤器确定给定产品是否已被给定用户购买,如果是,它将提高分数。
这种方法的问题是某些产品可能每月被购买数十万次,我不确定 ElasticSearch 在这种情况下的表现如何。
完美的解决方案是,如果我可以将购买历史记录放在单独的索引中,或者放在同一索引中但作为不同的文档类型(比如说“userspurchasehistory”)。示例文档:
{userId: 1234, purchesedProducts: [34,112323,1223,32342,31234]}
然后使用查询分数提升,它表示如下:如果术语 34 (productId) 出现在 userspurchasehistory(类型)文档的“purchesedProducts”(字段名称)中,其“userId”等于 1234,则将查询提升因子 2。
这里有什么想法或想法吗?
更新:
我对大量产品目录和大量销售数据进行了一些测试: 产品(类型)文档数:500 000 销售历史(类型)文档数:14 000 000 索引大小:2.5GB Elastic Serach:一个节点,所有默认设置
SalesHistory 文档是产品文档的子文档。 销售条目分布:
~20% of products: 40 entries
~20% of products: 30 entries
~20% of products: 20 entries
~20% of products: 10 entries
~20% of products: 5 entries
200 products with 10 000 sales entries (plus previously added 5-40 entries)
200 products with 5 000 sales entries (plus previously added 5-40 entries)
200 products with 2 500 sales entries (plus previously added 5-40 entries)
200 products with 1 000 sales entries (plus previously added 5-40 entries)
200 products with 500 sales entries (plus previously added 5-40 entries)
1 product 18 500 entries
示例查询:
curl -XGET "http://localhost:9200/demoproducts/_search" -d'
{
"query": {
"custom_filters_score": {
"query": {
"match_all": {}
}
},
"filters": [
{
"filter": {
"has_child": {
"type": "saleshistory",
"query": {
"term": {
"userId": {
"value": "28875"
}
}
}
}
},
"boost": 2
}
]
}
}'
结果:
{
"took": 33,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 500001,
"max_score": 2
...
}
}
当我向查询添加一些过滤器时(几乎在所有情况下,我们的查询都包含一些过滤器)响应时间约为 7 毫秒
结论
没有必要以任何其他方式将这种情况作为子文档来实现。
最佳答案
无需修改文档,您可以动态构建一个包含用户购买历史记录的条款查询。
curl -XGET "http://localhost:9200/demoproducts/_search" -d'
{
"query": {
"terms": {"id":["34","112323","1223","32342","31234"]}
}
}
}
关于ElasticSearch 根据不同类型的查询结果提高文档得分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21225323/