如何使用 ElasticSearch 组织嵌套对象的搜索?
How to organize a search of nested objects with ElasticSearch?
我正在尝试使用 ElasticSearch 在我的项目中组织搜索,但无法弄清楚一件事。
让我们简化上下文并假设有 2 个模型:用户及其消息。所以,我想提供两种类型的搜索:
- 查找消息我的文本
- 通过消息查找用户
短信消息(很简单)
它应该如何工作:用户输入 "notes about the meeting" 并且他会得到包含此文本的消息列表。
消息是这样存储在 ElasticSearch 中的:
{
"id" : "1",
"user_id" : "101",
"text": "hello"
}
因此,通过文本查找消息没有问题。
用户文本(问题)
它应该如何工作:用户输入 "notes about the meeting" 并且他会得到一个使用此文本编写消息的用户列表。
我不知道如何组织它,但我真的不喜欢它们中的任何一个。
想法 1
找到所有的消息,提取它们的 user_ids 然后 运行 SQL 像这样查询
SELECT * FROM users WHERE id IN ('101', '102', '103')
这是最明显的方法,但有一个问题——如何组织适当的分页?消息是分页的,但用户不是。
想法 2
将用户的消息作为嵌套对象存储在 ElasticSearch 中:
{
"id" : "101",
"name" : "Bob",
"messages" : [
{ "id" : "1", "text" : "hello" },
{ "id" : "2", "text" : "howdy?" },
{ "id" : "3", "text" : "bye" }
]
}
现在我可以通过ElasticSearch 一次查询找到用户。但是也有一些缺点:
- 添加新消息时我必须重新索引整个用户对象
- 我必须在 ElasticSearch 缓存中复制消息以提供两种类型的搜索:第一次作为单独的消息对象,第二次作为用户对象中的嵌套对象。我有很多数据(至少 10 亿条消息),所以这种重复会使我的缓存非常大(而且可能很慢?)。
你能建议我最好和最常用的解决这个问题的方法吗?
正如您所指出的,可以通过使用嵌套对象来解决,但更好的方法是使用父子关系。
您在嵌套对象中可能遇到的问题可以根据您的需要使用 parent-child relationship(consider reading the whole section especially this.) and use has_child or has_parent 查询来解决。
它将解决需要索引整个对象的问题。但是您需要考虑内存,因为 elasticsearch 在内存中存储子文档 ID(截至目前)。
我正在尝试使用 ElasticSearch 在我的项目中组织搜索,但无法弄清楚一件事。
让我们简化上下文并假设有 2 个模型:用户及其消息。所以,我想提供两种类型的搜索:
- 查找消息我的文本
- 通过消息查找用户
短信消息(很简单)
它应该如何工作:用户输入 "notes about the meeting" 并且他会得到包含此文本的消息列表。
消息是这样存储在 ElasticSearch 中的:
{
"id" : "1",
"user_id" : "101",
"text": "hello"
}
因此,通过文本查找消息没有问题。
用户文本(问题)
它应该如何工作:用户输入 "notes about the meeting" 并且他会得到一个使用此文本编写消息的用户列表。
我不知道如何组织它,但我真的不喜欢它们中的任何一个。
想法 1
找到所有的消息,提取它们的 user_ids 然后 运行 SQL 像这样查询
SELECT * FROM users WHERE id IN ('101', '102', '103')
这是最明显的方法,但有一个问题——如何组织适当的分页?消息是分页的,但用户不是。
想法 2
将用户的消息作为嵌套对象存储在 ElasticSearch 中:
{
"id" : "101",
"name" : "Bob",
"messages" : [
{ "id" : "1", "text" : "hello" },
{ "id" : "2", "text" : "howdy?" },
{ "id" : "3", "text" : "bye" }
]
}
现在我可以通过ElasticSearch 一次查询找到用户。但是也有一些缺点:
- 添加新消息时我必须重新索引整个用户对象
- 我必须在 ElasticSearch 缓存中复制消息以提供两种类型的搜索:第一次作为单独的消息对象,第二次作为用户对象中的嵌套对象。我有很多数据(至少 10 亿条消息),所以这种重复会使我的缓存非常大(而且可能很慢?)。
你能建议我最好和最常用的解决这个问题的方法吗?
正如您所指出的,可以通过使用嵌套对象来解决,但更好的方法是使用父子关系。
您在嵌套对象中可能遇到的问题可以根据您的需要使用 parent-child relationship(consider reading the whole section especially this.) and use has_child or has_parent 查询来解决。
它将解决需要索引整个对象的问题。但是您需要考虑内存,因为 elasticsearch 在内存中存储子文档 ID(截至目前)。