繁体   English   中英

多模型单指数方法-通过轮胎进行弹性搜索

[英]Multiple model single index approach - elasticsearch via tire

在我的多租户应用程序(基于每个帐户用户数的帐户)中,当用户文档更改时,我将如何更新特定帐户的索引。

通过Tyre gem使用Elasticsearch。

Rails 2.3应用程序-应用更改以启用对loe / tire提交的 Rails 2.3的支持

帐户模型:

  include Tire::Model::Search

  Tire.index('account_1') do
    create(
      :mappings => {
        :user => {
          :properties => {
            :name => { :type => :string, :boost => 10 },
            :company_name => { :type => :string, :boost => 5 }
          }
        },
        :comments => {
          :properties => {
            :description => { :type => :string, :boost => 5 }
          }
        }
      }
    )
  end

正如您在上面看到的,这里有用户和注释两个模型。 这是解决多个模型的单个索引的正确方法吗?

在那种情况下,当仅更改用户文档或注释文档时,如何更新索引?

通常,在为模型建立索引时,最好将自身属性及其关联建立索引。 因此,在这种情况下,如果要索引用户及其评论,则应在用户模型中具有索引,并为其关联所引用的注释建立索引,以便轮胎回调适用于用户模型以重新索引用户对象(如果模型中有任何属性)被改变了。 这仅适用于具有索引的模型。

如果您只想为关联建立索引,则需要具有钩子,这些钩子将在保存/销毁用户/注释模型后为帐户对象建立索引。 或者,您也可以使用:touch => true选项在更改用户/评论时触摸帐户模型。

示例:如果您要索引用户和评论,

  include Tire::Model::Search
  include Tire::Model::Callbacks

     mapping do
        indexes :id,                  :type => 'integer', :index    => :not_analyzed
        indexes :about_me,            :type => 'string',  :index    => :snowball
        indexes :name,                :type => 'string',  :index    => :whitespace

        indexes :comments do
          indexes :content,                  :type => 'string', :analyzer => 'snowball'
        end
    end

因此,这里的索引位于用户模型上,而user.comments是一个关联。 希望这个例子能解释

轮胎所有人Karmi发表的问题答案如下:

假设我们有一个Account类,并且我们处理商品实体。

在这种情况下,我们的Account类将具有以下内容:

class Account
  #...

  # Set index name based on account ID
  #
  def articles
      Article.index_name "articles-#{self.id}"
      Article
  end
end

因此,只要我们需要访问特定帐户的文章(用于搜索或建立索引),我们都可以简单地执行以下操作:

@account = Account.find( remember_token_or_something_like_that )

# Instead of `Article.search(...)`:
@account.articles.search { query { string 'something interesting' } }

# Instead of `Article.create(...)`:
@account.articles.create id: 'abc123', title: 'Another interesting article!', ...

在某些情况下,每个用户/帐户拥有一个单独的索引非常合适-但在您拥有成千上万个索引(或更多)的情况下,绝对不行。 在这种情况下,具有索引别名以及正确设置的筛选器和路由会更好。 我们将不根据租户身份对数据进行切片,而是根据时间对数据进行切片。

让我们看一下第二种情况,从大大简化的curl http:// localhost:9200 / _aliases?漂亮的输出开始:

{
  "articles_2012-07-02" : {
    "aliases" : {
      "articles_plan_pro" : {
      }
    }
  },
  "articles_2012-07-09" : {
    "aliases" : {
      "articles_current" : {
      },
      "articles_shared" : {
      },
      "articles_plan_basic" : {
      },
      "articles_plan_pro" : {
      }
    }
  },
  "articles_2012-07-16" : {
    "aliases" : {
    }
  }
}

您可以看到我们有三个索引,每周一个。 您可以看到有两个类似的别名:articles_plan_pro和articles_plan_basic-显然,具有“ pro”订阅的帐户可以在两周后搜索,但是具有“ basic”订阅的帐户只能在本周搜索。

还要注意,articles_current别名指向,例如,本周(我在2012年4月12日星期四撰写)。 下周的索引就在这里,等待和放置-当时间到了时,后台作业(cron,Resque worker,自定义脚本等)将更新别名。 Tire集成测试套件中的“滑动窗口”场景中有一个带有别名的漂亮示例。

现在,让我们不看看articles_shared别名,让我们看看使用此设置可以使用的技巧:

class Account
  # ...

  # Set index name based on account subscription
  #
  def articles
    if plan_code = self.subscription && self.subscription.plan_code
      Article.index_name "articles_plan_#{plan_code}"
    else
      Article.index_name "articles_shared"
    end
    return Article
  end
end

再次,我们为Article类设置一个index_name,其中包含我们的文档。 当当前帐户具有有效的订阅时,我们从订阅中获取plan_code,然后直接在相关索引中搜索该帐户:“基本”或“专业”。

如果该帐户没有订阅(他可能是“访客”类型),我们会将搜索定向到articles_shared别名。 使用该界面与以前一样简单,例如。 在ArticlesController中:

@account  = Account.find( remember_token_or_something_like_that )
@articles = @account.articles.search { query { ... } }
# ...

在这种情况下,我们不使用Article类作为索引的网关; 我们有一个单独的索引编制组件,一个Sinatra应用程序,充当Elasticsearch Bulk API的轻型代理,提供HTTP身份验证,文档验证(强制执行规则,如所需属性或以UTC形式传递的日期),并使用裸Tyre :: Index#import和Tire :: Index#store API。

这些API会与articles_currentindex别名通信,该别名会通过所述后台进程定期更新到当前星期。 这样,我们就取消了在单独的应用程序组件中设置索引名称的所有逻辑,因此我们不需要访问索引代理(它在单独的服务器上运行)中的Article或Account类。应用程序的组件。 无论索引的是哪个组件,都将根据articles_current别名进行索引; 无论要搜索哪个组件,都将搜索对该特定组件有意义的任何别名或索引。

暂无
暂无

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

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