在我的 Multi-Tenancy 应用程序(基于每个帐户的用户数的帐户)中,当更改用户文档时,如何更新特定帐户的索引。
我为每个帐户都有一个单独的索引,其中指定了每个模型的映射(用户和注释-只是示例实际应用程序具有许多模型)。在这种情况下,如果对用户模型或注释模型进行了任何更改,则必须更新为相关帐户创建的索引。这可能吗?如果可以,请告诉我。
我猜这是我指定情况下映射的方式。如果我错了纠正我。
帐户模型:
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
使用两个帐户索引映射正确创建了索引。但是,当映射中指定的任何模型发生更改时,我都看不到更新索引的方法。
每当添加新用户或更新用户时,都必须更新为相应帐户创建的索引。
最佳答案
这个问题来自Github问题Multiple model single index approach。在这里交叉张贴答案。
假设我们有一个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!', ...
在某些情况下,每个用户/帐户拥有一个单独的索引非常合适-但在您拥有成千上万个索引(或更多)的情况下,绝对不行。在这种情况下,具有索引别名以及正确设置的筛选器和路由会更好。我们不会根据租户身份对数据进行 slice ,而是根据时间对数据进行 slice 。
让我们看第二种情况,首先是大大简化的curl
http://localhost:9200/_aliases?pretty
输出:{
"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别名进行索引;无论要搜索哪个组件,都将搜索对该特定组件有意义的任何别名或索引。
关于ruby-on-rails - 单索引多类型-通过轮胎进行Elasticsearch分度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13743334/