【问题标题】:How to setup mappings for many-to-many association using elasticsearch-rails如何使用 elasticsearch-rails 为多对多关联设置映射
【发布时间】:2017-05-20 09:05:06
【问题描述】:

根据elasticseach docs,如果我的公司有很多分支机构,我想将员工与分支机构关联,我会这样做

PUT /company
{
    "mappings": {
        "branch": {},
        "employee"{
            "_parent": {
                "type": "branch"
            }
        }
    }
}

同样可以实现,用户使用Ruby-on-Rail,如下

class Branch < ActiveRecord::Base
  include Elasticsearch::Model

  has_many :employees, dependent: :destroy

  index_name 'company'

  mapping do
    indexes :name
  end

  after_commit lambda { __elasticsearch__.index_document  },  on: :create
  after_commit lambda { __elasticsearch__.update_document },  on: :update
  after_commit lambda { __elasticsearch__.delete_document },  on: :destroy
end

class Employee < ActiveRecord::Base
  include Elasticsearch::Model

  belongs_to :branch

  index_name 'company'

  mapping _parent: { type: 'branch' }, _routing: { required: true } do
    indexes :name
    indexes :email
  end

  after_commit lambda { __elasticsearch__.index_document(parent: branch_id)  },  on: :create
  after_commit lambda { __elasticsearch__.update_document(parent: branch_id) },  on: :update
  after_commit lambda { __elasticsearch__.delete_document(parent: branch_id) },  on: :destroy
end

module Searchable
  INDEX_NAME = 'company'

  def create_index!(options={})
    client = Branch.__elasticsearch__.client
    client.indices.delete index: INDEX_NAME rescue nil if options[:force]

    settings = Branch.settings.to_hash.merge Employee.settings.to_hash
    mappings = Branch.mappings.to_hash.merge Employee.mappings.to_hash

    client.indices.create index: INDEX_NAME,
                          body: {
                            settings: settings.to_hash,
                            mappings: mappings.to_hash }
  end

  extend self
end

如何设置 elasticsearch rails 以提供以下映射?

PUT /my_index/_mapping/blogpost
{
  "blogpost": {
    "properties": {
      "body": {
        "type": "text",
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        }
      },
      "title": {
        "type": "text",
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        }
      },
      "user": {
        "properties": {
          "name": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "id": {
            "type": "long"
          }
        }
      }
    }
  },
  "user": {
    "properties": {
      "dob": {
        "format": "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis",
        "type": "date"
      },
      "name": {
        "type": "text",
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        }
      },
      "email": {
        "type": "text",
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        }
      }
    }
  }
}

【问题讨论】:

    标签: ruby-on-rails elasticsearch many-to-many denormalization mappings


    【解决方案1】:

    这行得通

    用户

    class User < ApplicationRecord
      include Elasticsearch::Model
      has_and_belongs_to_many :blogposts, touch: true
    
      index_name 'blog'
    
      mapping do
        indexes :name
        indexes :email
      end
    
      after_commit lambda { __elasticsearch__.index_document  },  on: :create
      after_touch  lambda { __elasticsearch__.index_document  },  on: :touch
      after_commit lambda { __elasticsearch__.update_document },  on: :update
      after_commit lambda { __elasticsearch__.delete_document },  on: :destroy
    end
    

    博文

    class Blogpost < ApplicationRecord
      include Elasticsearch::Model
      has_and_belongs_to_many :user, touch: true
    
      index_name 'blog'
    
      mapping do
        indexes :title
        indexes :body
    
        indexes :user do
          indexes :id, type: 'long'
          indexes :name, type: 'string' do
            indexes :raw, type: 'keyword', index: 'not_analyzed'
          end
        end
      end
    
      def as_indexed_json(options={})
        hash = self.as_json()
        hash['user.id'] = self.user.first.id
        hash['user.name'] = self.user.first.name
        hash
      end
    
    
      after_commit lambda { __elasticsearch__.index_document  },  on: :create
      after_touch  lambda { __elasticsearch__.index_document  },  on: :touch
      after_commit lambda { __elasticsearch__.update_document },  on: :update
      after_commit lambda { __elasticsearch__.delete_document },  on: :destroy
    end
    

    可搜索模块 模块可搜索 INDEX_NAME = '博客'

      def create_index!(options={})
        client = User.__elasticsearch__.client
        client.indices.delete index: INDEX_NAME rescue nil if options[:force]
    
        settings = User.settings.to_hash.merge Blogpost.settings.to_hash
        mappings = User.mappings.to_hash.merge Blogpost.mappings.to_hash
    
        client.indices.create index: INDEX_NAME,
                              body: {
                                  settings: settings.to_hash,
                                  mappings: mappings.to_hash }
      end
    
      def setup
        Searchable.create_index! force: true
    
        10.times do
          n = Faker::Name.name
          u = User.create name: n,
                          email: Faker::Internet.free_email(n.split(' ').last)
    
          rand(1..10).times do
            s = Faker::Lorem.sentence
            u.blogposts.create title: s.split(' ').first, body: s
          end
        end
    
        User.__elasticsearch__.refresh_index!
      end
    
      extend self
    end
    

    【讨论】:

      猜你喜欢
      • 2011-01-03
      • 1970-01-01
      • 2011-07-04
      • 2011-01-19
      • 1970-01-01
      • 2015-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多