首页 > 解决方案 > 跨时间的多标准搜索

问题描述

我正在寻找一种优雅且可扩展的方式来跨时间搜索某些实体的元信息。

让我们看一下实体 A 和 B 随时间变化的以下元数据

[{
    "idEntity": "A",
    "name": "Name of A",
    "rating": 0.5,
    "description": "Some short description of A",
    "createdAtWeek": 1
}, {
    "idEntity": "B",
    "name": "Name of B",
    "rating": 0.2,
    "description": "Some short description of B",
    "createdAtWeek": 1
}, {
    "idEntity": "A",
    "name": "Name of A improved",
    "rating": 0.5,
    "description": "Some longer description of A",
    "createdAtWeek": 2
}, {
    "idEntity": "A",
    "name": "Name of A improved",
    "rating": 0.6,
    "description": "Some longer description of A",
    "createdAtWeek": 3
}]

我希望能够找到最后一个元匹配的实体(唯一)rating >= 0.2并且of在它们的description. 我也希望能够过去寻找这些相同的标准,但这需要给我不同的结果。

通过 Mongo 进行此操作的最简单方法是创建一个聚合管道,但如果集合变得越来越大,这将太慢。

因此,我去复制了所有文档,以便每周 (1-3) 获得完整的数据,这使我可以createdAtWeek直接将其包含在查询中,并确保我在不同时间获得一致的结果。

但是你可以看到这会导致什么,巨大的重复使收藏变得一文不值。

因此,我尝试将这些文档存储在 Solr 中,但是在查看文档时,似乎没有办法首先按实体和日期对结果进行分组,然后在分组中进行搜索。

是否有另一种方法可以在不实际复制的情况下实现与复制相同的结果?

标签: mongodbsearchsolr

解决方案


Solr Block Join Query Parser 可以处理这种操作。

数据结构向分层系统变化,createdAtWeek并被替换为validSince_ivalidUntil_i

/* Entity A */
{
  "path_s": "1.entity",
  "id": "A",
  "_childDocuments_": [
    {
      "path_s": "2.metadata.rating",
      "id": "2.metadata.rating.1",
      "_childDocuments_": [
        {
          "path_s": "3.metadata.rating.timeValidity",
          "id": "2.metadata.rating.timeValidity.1",
          "validSince_i": -1,
          "validUntil_i": 2,
          "value_f": 0.5
        },
        {
          "path_s": "3.metadata.rating.timeValidity",
          "id": "2.metadata.rating.timeValidity.2",
          "validSince_i": 3,
          "validUntil_i": 9999999,
          "value_f": 0.6
        }
      ]
    },
    {
      "path_s": "2.metadata.description",
      "id": "2.metadata.description.1",
      "_childDocuments_": [
        {
          "path_s": "3.metadata.description.timeValidity",
          "id": "2.metadata.description.timeValidity.1",
          "validSince_i": -1,
          "validUntil_i": 1,
          "value_txt_en": "Some short description of A"
        },
        {
          "path_s": "3.metadata.description.timeValidity",
          "id": "2.metadata.description.timeValidity.2",
          "validSince_i": 2,
          "validUntil_i": 9999999,
          "value_txt_en": "Some longer description of A"
        }
      ]
    }
  ]
}
/* Entity B */
{
  "path_s": "1.entity",
  "id": "B",
  "_childDocuments_": [
    {
      "path_s": "2.metadata.rating",
      "id": "2.metadata.rating.2",
      "_childDocuments_": [
        {
          "path_s": "3.metadata.rating.timeValidity",
          "id": "2.metadata.rating.timeValidity.3",
          "validSince_i": -1,
          "validUntil_i": 9999999,
          "value_f": 0.2
        }
      ]
    }
  ]
}

BlockJoin 现在可以与 faceting 一起使用,只要 timeValidities 没有像这样相互重叠:

fq={!parent which="path_s:1.entity"}(path_s:3.metadata.rating.timeValidity AND validUntil_i:[2 TO *] AND value_f:[0.3 TO *])&fq={!parent which="path_s:1.entity"}(path_s:3.metadata.description.timeValidity AND validUntil_i:[2 TO *] AND value_txt_en:short)&q=*:*

它不返回任何实体,因为在第 2 周之后没有实体rating >= 0.3的描述包含short

运行以下工作也很好

fq={!parent which="path_s:1.entity"}(path_s:3.metadata.rating.timeValidity AND validUntil_i:[2 TO *] AND value_f:[0.3 TO *])&fq={!parent which="path_s:1.entity"}(path_s:3.metadata.description.timeValidity AND validUntil_i:[2 TO *] AND value_txt_en:longer)&q=*:*

如您所见,实体 A 显示为在一周 >= 2 后其评级 >= 0.3 且描述包含longer.

需要声明性能方面,但它可以完成工作并避免重复。


推荐阅读