首页 > 解决方案 > 在 Elasticsearch 中搜索对象数组

问题描述

我将调查回复存储在我的 ES 中,所以发生的情况是人们使用移动应用程序填写调查表,这些表单回复被发送到后端,然后像这样存储在 ES 中,这就是表单中问题的答案是商店

answers {
  "uKeCywV4SAgD8YGReSkn" : {
              "_id" : "b465de5e-5468-40fe-8a8d-fc02083",
              "responseVersionNumber" : 1,
              "options" : [
                {
                  "id" : "32700fb5-51d2-4617-b65f-831b83c88080"
                },
                {
                  "id" : "32700fb5-51d2-4617-b65f-831b83c87777"
                }
}

answers文档在其问题 ID 下包含每个问题的答案。您在下面看到的字符串是问题 ID,与所有其他答案都存储在 ES 中的相应问题 ID 下的方式相同,该问题 ID 位于该响应的相应文档中。

现在我想搜索这些答案,上面的答案响应是 mcq 多选类型,因为您可以看到文本字段(包含)答案值(即用户园艺和运动的爱好)和选项 id 数组两者都可以用于此,我可以将选项 id 数组从我的网络应用程序发送到 ES 或文本值(或我们称之为选项标签),也可以使用问题 ID,例如假设我有一个问题id q1 所以我希望我的查询说给我问题 q1 同时有答案 a1 和 a2 的文档

我一直想探索选项 id 方法,这是我为它构建的示例查询。

 {
    "_source": {"includes": ["answers.uKeCywV4SAgD8YGReSkn.text", "answers.uKeCywV4SAgD8YGReSkn.questionTypeCode"]},
    "query": {
        "bool": {
            "filter": [{
                "bool": {
                    "must": [{
                        "match": {
                            "answers.uKeCywV4SAgD8YGReSkn.options.id": "32700fb5-51d2-4617-b65f-831b83c88080"
                        }
                    },
                        {
                        "match": {
                            "answers.uKeCywV4SAgD8YGReSkn.options.id": "32700fb5-51d2-4617-b65f-831b83c87777"
                        }
                    }
                    ]
                }
            }, {
                "match": {
                    "formId": "hHhcLKh9st1vFr8nDY4a"
                }
            }, {
                "range": {
                    "_updated_at": {
                        "from": "1970-01-01T00:00:00.000+0000",
                        "include_lower": true,
                        "include_upper": true,
                        "to": null
                    }
                }
            }]
        }
    }
 }

我想知道使用这种方法而不是text使用两个选项标签搜索字段是否有任何缺点

根据映射,这是两个字段的设置方式

"questionId": {
   "type": "keyword",
   "index": false
},

"text": {
    "type": "text"
},

"options": {
    "enabled": false
},

标签: elasticsearch

解决方案


你的问题有点难以理解......但对我来说可能还为时过早:) 我不太明白“选项 ID”字段应该在这里做什么。您的答案是否用于多个问题?还是您的答案有多种选择?如果是这样,为什么用户还可以回复文字?另外,为什么要将所有字段都放在文档的两层深处?为什么不把它们平放?将字段命名为 questionID 似乎很麻烦。

虽然我不太确定你在这里问什么,但我可以提出一些可能会有所帮助的建议。

我最近一直在玩 Elasticsearch,特别是嵌套对象数组。您可能正在寻找的是嵌套数据类型。我强烈建议您阅读它的文档

简而言之,它将允许您将“选项 ID”存储为嵌套对象,这些对象可以使用自己的嵌套查询进行查询。这是完成嵌套对象搜索的最简单方法。

首先,您需要指定映射以告诉 Elasticsearch “选项”是嵌套数据类型:

PUT INDEX_NAME
{
  "mappings": {
    "DOCUMENT_TYPE": {
      "properties": {
        "options": {"type": "nested"}
      }
    }
  }
}

然后,在您为文档编制索引后,您可以使用嵌套查询来查询该字段。例如,如果您想要选项 ID“ID_123”的所有答案:

GET INDEX_NAME/_search
{
  "query": {
    "nested": {
      "path": "options",
      "query": {
        "match": {
          "options.id.keyword": "ID_123"
        }
      }
    }
  }
}

您还可以“布尔”嵌套查询以添加更多参数,例如,如果您想要选项 ID 的每个答案,这在过去一天也已更新。

我希望这在某种程度上有所帮助。如果没有,请尝试更清楚地描述您尝试做的事情:)


推荐阅读