使用 Elasticsearch [Ruby、ActiveRecord、elasticsearch-model 进行关联模型搜索的方法
Approach for associated model searching with Elasticsearch [Ruby, ActiveRecord, elasticsearch-model]
我有一个关于在 Elasticsearch
中搜索时选择最佳方法的问题。
我有Ruby关RailsAPI,有ActiveRecord
,还有Elasticsearch
(elasticsearch-model
gem) .
这是一个简单的 API,其中 returns projects
(项目 AR 模型),我在其中设置索引:
mapping dynamic: false do
indexes :created_at, type: 'date'
end
然后我直接从控制器搜索 Elasticsearch 和 return AR 关系。它运行良好。
现在我正在尝试将 categories
添加到 projects
,如 categories has_many projects
和 projects belongs_to categories
。我想知道两件事:
我现在应该如何查询以获取特定类别的项目,我应该将其重新实现为 return result = Category.search(...)
和 return result.jobs
,还是仍然通过以下方式寻求projects
,但按 category_id
?
搜索
如何在 Elasticsearch 中结合 Category
和 Project
以实现从特定类别和多个类别中搜索项目?合并映射?
提前致谢!
我的第一个想法是您的用例非常简单。您根本不需要 Elasticsearch。您可以简化并仅使用 ActiveRecord,select by SQL 和 return 记录。您不需要 Elasticsearch 为您的用例提供的任何功能,这样做只是为您自己创造更多的工作。
但是,我假设您进行迭代开发并且您的使用会变得更加复杂。证明使用 Elasticsearch 的合理性。
关系和非关系数据
ActiveRecord 是一个 ORM for relational data. Typicalhttps://www.elastic.co/guide/en/elasticsearch/reference/current/documents-indices.htmlly it sits on top of a Structured Query Language 强大的关系数据库。它非常好地支持关系(Rails 说法中的关联)。
Elasticsearch 是 non relational document store,在倒排索引中将信息存储为 JSON。这允许非常快速的全文搜索(以及其他用途)。它不能很好地支持文档之间的关系。它旨在不关联数据!它希望您不存储关系,而是不断重复数据,这与 SQL 方法相反。这称为非规范化,更多内容见下文。
这些是关于数据存储的非常不同的思考方式!这并不意味着他们在一起玩得不好。如果使用得当,它们可以很好地协同工作。然而,他们采取不同的思维方式。在我看来,重要的是要很好地掌握每个背后的基础知识,以便对如何使用它们做出合理的判断。
Elasticsearch 很棒 documentation。我建议您花几个小时阅读它。
Elasticsearch 是如何做关联的?
您关心问题中的基本 has-many
关联,那么 Elastic 如何处理这些关联?有哪些选择?
There are 4 major options. I think you should denormalize 您的数据在这里。
我想你想 return 某些类别的所有项目。因此,您应该创建一个索引,其中包含每个类别的文档。每个类别都应包含其项目的完整列表。然后,您可以查询类别和 return 所有项目。
这是一种方法。您的用例非常简单,对我来说感觉有点矫枉过正,您可以使用上面链接的 Elasticsearch 的 4 个主要选项中的任何一个来解决这个问题。或者理想情况下根本不使用 Elasticsearch。
如果您提供有关用例的更多详细信息,我将能够更多地讨论您可以使用的方法。
// 映射(嵌套类别)
mapping dynamic: false do
indexes :created_at, type: 'date'
indexes :categories, type: 'nested' do
indexes :name, type: :text, analyzer: :english
end
end
// json
def as_indexed_json(_options = nil)
{
created_at: created_at,
# in case project belong_to category
# categories: [category.name, Category::DEFAULT].map do ...
categories: categories.map do |category|
{
name: category.name
}
end
}
end
// 搜索功能(elasticsearch DSL) 因为你想按类别搜索项目
def by_categories(categories)
filters = []
categories.each { |category|
filters.push term: {"categories.name":category.name}
}
Project.__elasticsearch__.search(
query: {
nested: {
path: "categories",
query: {
bool: {
filter:{
bool:{
should:filters
}
}
}
}
}
}
)
end
我有一个关于在 Elasticsearch
中搜索时选择最佳方法的问题。
我有Ruby关RailsAPI,有ActiveRecord
,还有Elasticsearch
(elasticsearch-model
gem) .
这是一个简单的 API,其中 returns projects
(项目 AR 模型),我在其中设置索引:
mapping dynamic: false do
indexes :created_at, type: 'date'
end
然后我直接从控制器搜索 Elasticsearch 和 return AR 关系。它运行良好。
现在我正在尝试将 categories
添加到 projects
,如 categories has_many projects
和 projects belongs_to categories
。我想知道两件事:
我现在应该如何查询以获取特定类别的项目,我应该将其重新实现为 return result = Category.search(...)
和 return result.jobs
,还是仍然通过以下方式寻求projects
,但按 category_id
?
如何在 Elasticsearch 中结合 Category
和 Project
以实现从特定类别和多个类别中搜索项目?合并映射?
提前致谢!
我的第一个想法是您的用例非常简单。您根本不需要 Elasticsearch。您可以简化并仅使用 ActiveRecord,select by SQL 和 return 记录。您不需要 Elasticsearch 为您的用例提供的任何功能,这样做只是为您自己创造更多的工作。
但是,我假设您进行迭代开发并且您的使用会变得更加复杂。证明使用 Elasticsearch 的合理性。
关系和非关系数据
ActiveRecord 是一个 ORM for relational data. Typicalhttps://www.elastic.co/guide/en/elasticsearch/reference/current/documents-indices.htmlly it sits on top of a Structured Query Language 强大的关系数据库。它非常好地支持关系(Rails 说法中的关联)。
Elasticsearch 是 non relational document store,在倒排索引中将信息存储为 JSON。这允许非常快速的全文搜索(以及其他用途)。它不能很好地支持文档之间的关系。它旨在不关联数据!它希望您不存储关系,而是不断重复数据,这与 SQL 方法相反。这称为非规范化,更多内容见下文。
这些是关于数据存储的非常不同的思考方式!这并不意味着他们在一起玩得不好。如果使用得当,它们可以很好地协同工作。然而,他们采取不同的思维方式。在我看来,重要的是要很好地掌握每个背后的基础知识,以便对如何使用它们做出合理的判断。
Elasticsearch 很棒 documentation。我建议您花几个小时阅读它。
Elasticsearch 是如何做关联的?
您关心问题中的基本 has-many
关联,那么 Elastic 如何处理这些关联?有哪些选择?
There are 4 major options. I think you should denormalize 您的数据在这里。
我想你想 return 某些类别的所有项目。因此,您应该创建一个索引,其中包含每个类别的文档。每个类别都应包含其项目的完整列表。然后,您可以查询类别和 return 所有项目。
这是一种方法。您的用例非常简单,对我来说感觉有点矫枉过正,您可以使用上面链接的 Elasticsearch 的 4 个主要选项中的任何一个来解决这个问题。或者理想情况下根本不使用 Elasticsearch。
如果您提供有关用例的更多详细信息,我将能够更多地讨论您可以使用的方法。
// 映射(嵌套类别)
mapping dynamic: false do
indexes :created_at, type: 'date'
indexes :categories, type: 'nested' do
indexes :name, type: :text, analyzer: :english
end
end
// json
def as_indexed_json(_options = nil)
{
created_at: created_at,
# in case project belong_to category
# categories: [category.name, Category::DEFAULT].map do ...
categories: categories.map do |category|
{
name: category.name
}
end
}
end
// 搜索功能(elasticsearch DSL) 因为你想按类别搜索项目
def by_categories(categories)
filters = []
categories.each { |category|
filters.push term: {"categories.name":category.name}
}
Project.__elasticsearch__.search(
query: {
nested: {
path: "categories",
query: {
bool: {
filter:{
bool:{
should:filters
}
}
}
}
}
}
)
end