繁体   English   中英

使用 Elasticsearch 进行关联模型搜索的方法 [Ruby、ActiveRecord、elasticsearch-model]

[英]Approach for associated model searching with Elasticsearch [Ruby, ActiveRecord, elasticsearch-model]

我有一个关于在Elasticsearch中搜索时选择最佳方法的问题。

我有 Ruby off Rails API、 ActiveRecordElasticsearchelasticsearch-model gem)。

这是一个简单的 API,它返回projects (Project AR 模型),我在其中设置了索引:

mapping dynamic: false do
indexes :created_at, type: 'date'
end

然后我简单地在 Elasticsearch 上进行搜索并直接从控制器返回 AR 关系。 它工作得很好。

现在,我正在尝试向projects添加categories ,如categories has_many projectsprojects belongs_to categories 我想知道两件事:

现在我应该如何查询以从特定类别中获取项目,我应该重新实现它以返回result = Category.search(...)并返回result.jobs ,还是仍然按projects搜索,但按category_id搜索?

如何在 Elasticsearch 中结合CategoryProject ,以便从特定类别和各种多个类别中搜索项目? 合并映射?

提前致谢!

我的第一个是你的用例非常简单。 您根本不需要 Elasticsearch。 您可以简化和使用 ActiveRecord,通过 SQL 选择并返回记录。 您不需要 Elasticsearch 为您的用例提供的任何功能,这样做只是为自己创造更多的工作。

但是,我会假设您在迭代开发,并且您的使用将变得更加复杂。 证明使用 Elasticsearch 的合理性。

关系和非关系数据

ActiveRecord 是关系数据的ORM 典型的 https://www.elastic.co/guide/en/elasticsearch/reference/current/documents-indices.htmlly 它位于结构化查询语言驱动的关系数据库之上。 它非常好地支持关系(Rails 中的关联)。

Elasticsearch 是一个非关系文档存储,将信息作为 JSON 存储在倒排索引中。 这允许非常快速的全文搜索(以及其他用途)。 它不能很好地支持文档之间的关系。 它旨在不关联数据! 它希望您不存储关系,而是不断重复数据,这与 SQL 方法相反。 这称为非规范化,更多内容见下文。

这些是关于数据存储的非常不同的思考方式! 这并不意味着他们不能很好地一起玩。 如果使用得当,它们可以很好地协同工作。 然而,他们采取不同的思维方式。 在我看来,重要的是要很好地掌握每个背后的基本原理,以便对如何使用它们做出合理的判断。

Elasticsearch 有很好的文档 我建议你花几个小时阅读它。

Elasticsearch 如何做关联?

您关心问题中的基本has-many关联,那么 Elastic 如何处理这些关联? 有什么选择?

有4个主要选项。 我认为你应该在这里非规范化你的数据。

我认为您想返回某些类别的所有项目。 因此,您应该创建一个索引,其中每个类别包含一个文档。 每个类别都应包含其项目的完整列表。 然后您可以查询一个类别并返回它的所有项目。

这是一种方法。 您的用例非常简单,对我来说感觉有点矫枉过正,您可以使用上面链接的 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM