我正试图找出如何在Riak中建模数据。假设您正在构建具有两个功能,新闻和产品的CMS。您需要能够为多个客户端X和Y存储此信息。您通常如何构建此信息?
每个客户端一个存储桶,然后是两个密钥 news 和产品。在每个键下存储多个对象,然后使用map / reduce命令它们。
将新闻和产品存储在同一个存储桶中,但每个新闻项和产品项都有一个新的自动生成密钥。也就是说,X为一个桶,Y为一个。
每个客户端/功能组合一个存储桶,即存储桶将是 X-news , X-products , Y-news < / em>和 Y-products 。然后在整个存储桶上使用map / reduce按顺序返回结果。
哪种方法可以解决这个问题?
答案 0 :(得分:15)
我会创建2个桶:新闻和产品。 然后我会在每个存储桶中使用客户端名称为密钥添加前缀。 我可能还会在新闻密钥中包含日期,以方便日期范围。
news/acme_2011-02-23_01
news/acme_2011-02-23_02
news/bigcorp_2011-02-21_01
并可选择在产品名称前加上类别名称
products/acme_blacksmithing_anvil
products/bigcorp_databases_oracle
然后在您的地图/缩小中,您可以使用key filtering:
// BigCorp News items
{
"inputs":{
"bucket":"news",
"key_filters":[["starts_with", "bigcorp"]]
}
// ... rest of mapreduce job
}
// Acme Blacksmithing items
{
"inputs":{
"bucket":"products",
"key_filters":[["starts_with", "acme_blacksmithing"]]
}
// ... rest of mapreduce job
}
// News for all clients from Feb 12th to 19th
{
"inputs":{
"bucket":"news",
"key_filters":[["tokenize", "_", 2],
["between", "2011-02-12", "2011-02-19"]]
}
// ... rest of mapreduce job
}
答案 1 :(得分:7)
比使用密钥过滤(根据Kev Burns的建议)更有效的方法是使用Secondary Indexes或Riak Search来模拟这种情况。
请查看我对Which clustered NoSQL DB for a Message Storing purpose?和Links in Riak: what can they do/not do, compared to graph databases?的回答,以便对类似案例进行讨论。
根据您的使用情况,您需要做出几个决定。在所有情况下,您都应该从公司存储桶开始,以便每个公司都有一个唯一的密钥。
1)是否将感兴趣的项目存储在两个独立的存储桶(新闻和产品)或一个存储器中(如 items_of_interest )取决于您的偏好和查询的简易性。如果您总是在一个查询中查询公司的新闻和产品,那么您也可以将它们存储在一个存储桶中。但我建议使用2个单独的,以便更容易跟踪它们,特别是如果你有“公司X - 产品”和“公司X - 新闻”的单独选项卡或页面。如果您需要将它们组合成单个Feed,您将进行2个查询(一个用于新闻,一个用于产品),并将它们组合在客户端代码中(按日期或其他方式)。
2)如果新闻/产品项目可以包含一个且只有一个公司,则为每个项目在 company_key 上创建一个二级索引。这样,您就可以通过该公司的二级索引(2i)查询轻松获取公司的所有新闻或产品。
3)如果存在多对多关系(如果新闻/产品项目可能属于多家公司(可能新闻项目是关于两家独立公司的合资企业)),那么我建议建立关系< em>作为单独的Riak对象。例如,您可以创建一个提及存储桶,对于新闻报道中提到的每个公司,您将插入一个Mention对象,该对象具有自己的唯一键,company_key的二级索引,值将为包含类型('新闻'或'产品')和item_key(新闻密钥或产品密钥)。 提取关系以分离这样的Riak对象可以让你做很多有趣的事情 - 使用Riak Search任意标记它们,查询它们以进行订阅事件通知等。