作者:Sagar Patel, Developer and Community Member
在我之前的文章 “Elasticsearch: 运用 Pinned query 来提高文档的排名 (7.5发行版新功能)”,我已经详述这个话题了。不过在今天的这篇文章中,它有一些额外的一些知识点可以让我们更加深入地了解这个 Pinned query。算是对之前的文章做一个补充吧。
在本文中,通过实际用例了解 Elasticsearch 中的 pinned query 如何为你服务。
什么是 pinned query,我们该如何运用它?
Pinned query 首先在 Elasticsearch 7.4 中发布,用于将所选文档或文档提升到位于特定查询结果顶部的任何其他文档之上。 它可用于文档提升或引导搜索,即使相关性得分较低,某些文档也必须出现在顶部结果中。
以下是 pinned query 的一些实际用例:
- 你正在开发一个知识中心并监控用户对每篇文章的点击。 给定查询的最常点击文章应显示在页面顶部。
- 你想在搜索顶部显示新推出的产品作为促销。 此外,对于某些产品,你希望将此功能用于季节性营销。
Pinned query 使用
让我们首先使用示例产品数据集来开发我们的 pinned query。
示例数据索引
1. PUT product/_bulk
2. {"index":{"_id":"prod101"}}
3. {"brand":"Apple","model":"iphone 11","price":800}
4. {"index":{"_id":"prod102"}}
5. {"brand":"Samsung","model":"galaxy m32","price":700}
6. {"index":{"_id":"prod103"}}
7. {"brand":"Apple","model":"iphone 13","price":1000}
8. {"index":{"_id":"prod104"}}
9. {"brand":"Apple","model":"iphone 12","price":900}
10. {"index":{"_id":"prod105"}}
11. {"brand":"Apple","model":"iphone 7","price":400}
没有使用 pinned query 的搜索
1. POST product/_search?filter_path=**.hits
2. {
3. "query": {
4. "match": {
5. "model": "iphone"
6. }
7. }
8. }
上面命令的响应为:
`
1. {
2. "hits": {
3. "hits": [
4. {
5. "_index": "product",
6. "_id": "prod101",
7. "_score": 0.2876821,
8. "_source": {
9. "brand": "Apple",
10. "model": "iphone 11",
11. "price": 800
12. }
13. },
14. {
15. "_index": "product",
16. "_id": "prod103",
17. "_score": 0.2876821,
18. "_source": {
19. "brand": "Apple",
20. "model": "iphone 13",
21. "price": 1000
22. }
23. },
24. {
25. "_index": "product",
26. "_id": "prod104",
27. "_score": 0.2876821,
28. "_source": {
29. "brand": "Apple",
30. "model": "iphone 12",
31. "price": 900
32. }
33. },
34. {
35. "_index": "product",
36. "_id": "prod105",
37. "_score": 0.2876821,
38. "_source": {
39. "brand": "Apple",
40. "model": "iphone 7",
41. "price": 400
42. }
43. }
44. ]
45. }
46. }
`
目前,你可以看到产品按相关性排序,并且最近推出的项目不会出现在顶部。 现在让我们看看如何使用 pinned query 在顶部推广最近发布的产品。
Pinned query 示例
在这里,我们正在努力推广最新的 iPhone。
`
1. POST product/_search?filter_path=**.hits
2. {
3. "query": {
4. "pinned": {
5. "ids": [
6. "prod103",
7. "prod104"
8. ],
9. "organic": {
10. "match": {
11. "model": "iphone"
12. }
13. }
14. }
15. }
16. }
`
上面的命令返回如下的结果:
`
1. {
2. "hits": {
3. "hits": [
4. {
5. "_index": "product",
6. "_id": "prod103",
7. "_score": 1.7014124e+38,
8. "_source": {
9. "brand": "Apple",
10. "model": "iphone 13",
11. "price": 1000
12. }
13. },
14. {
15. "_index": "product",
16. "_id": "prod104",
17. "_score": 1.7014122e+38,
18. "_source": {
19. "brand": "Apple",
20. "model": "iphone 12",
21. "price": 900
22. }
23. },
24. {
25. "_index": "product",
26. "_id": "prod101",
27. "_score": 0.2876821,
28. "_source": {
29. "brand": "Apple",
30. "model": "iphone 11",
31. "price": 800
32. }
33. },
34. {
35. "_index": "product",
36. "_id": "prod105",
37. "_score": 0.2876821,
38. "_source": {
39. "brand": "Apple",
40. "model": "iphone 7",
41. "price": 400
42. }
43. }
44. ]
45. }
46. }
`
在 Elasticsearch 返回的结果之上,你可以分别看到 iPhone 13 和 iPhone 12,其他结果直接位于它们下方。
如何使用具有多个索引的 pinned query
如果你想跨多个索引搜索产品,请使用下面的查询和索引名称。
`
1. GET /_search
2. {
3. "query": {
4. "pinned": {
5. "docs": [
6. {
7. "_index": "product-01",
8. "_id": "prod101"
9. },
10. {
11. "_index": "product-01",
12. "_id": "prod102"
13. },
14. {
15. "_index": "product-02",
16. "_id": "prod105"
17. }
18. ],
19. "organic": {
20. "match": {
21. "model": "iphone"
22. }
23. }
24. }
25. }
26. }
`
注意:请注意,你最多只能为 pinned query 提供 100 个 ID。
在以下情况下, pinned query 结果将不存在
Elasticsearch 默认根据相关性返回文档; 但是,假设对于某些查询,你需要特定的排序选项,例如基于日期、产品数量等。在这种情况下,你不会收到固定结果,因为排序没有考虑相关性。
让我们尝试推广更便宜的 iPhone 7 和 iPhone 11 并使用价格排序。
`
1. POST product/_search?filter_path=**.hits
2. {
3. "sort": [
4. {
5. "price": {
6. "order": "desc"
7. }
8. }
9. ],
10. "query": {
11. "pinned": {
12. "ids": [
13. "prod105",
14. "prod101"
15. ],
16. "organic": {
17. "match": {
18. "model": "iphone"
19. }
20. }
21. }
22. }
23. }
`
上面命令返回的结果是:
`
1. {
2. "hits": {
3. "hits": [
4. {
5. "_index": "product",
6. "_id": "prod103",
7. "_score": null,
8. "_source": {
9. "brand": "Apple",
10. "model": "iphone 13",
11. "price": 1000
12. },
13. "sort": [
14. 1000
15. ]
16. },
17. {
18. "_index": "product",
19. "_id": "prod104",
20. "_score": null,
21. "_source": {
22. "brand": "Apple",
23. "model": "iphone 12",
24. "price": 900
25. },
26. "sort": [
27. 900
28. ]
29. },
30. {
31. "_index": "product",
32. "_id": "prod101",
33. "_score": null,
34. "_source": {
35. "brand": "Apple",
36. "model": "iphone 11",
37. "price": 800
38. },
39. "sort": [
40. 800
41. ]
42. },
43. {
44. "_index": "product",
45. "_id": "prod105",
46. "_score": null,
47. "_source": {
48. "brand": "Apple",
49. "model": "iphone 7",
50. "price": 400
51. },
52. "sort": [
53. 400
54. ]
55. }
56. ]
57. }
58. }
`
它应该出现在顶部,因为我们正在尝试推广 iPhone 7 和 iPhone 11。但是,在这种情况下,将不会考虑 pinned query,因为我们按 price 降序排序。