2

我有用户模型对象,其中包含很少的字段(属性,如果您愿意)。说“名字”、“姓氏”、“城市”和“出生年份”。每个用户还获得“唯一 ID”。

我希望能够通过他们进行搜索。我该如何正确地做到这一点?如何做到这一点?

我的理解(几乎适用于任何键值存储——首先是键,然后是值)

u:123456789 = serialized_json_object

(“u”作为用户密钥的简单前缀,123456789 是“唯一 id”)。

现在,考虑到我希望能够按名字和姓氏进行搜索,我可以保存在:

f:Steve = u:384734807,u:2398248764,u:23276263 f:Alex = u:12324355,u:121324334

所以键是“f”——这是名字的前缀,而“Steve”是实际的名字。对于“u:Steve”,我们将所有属于“Steve”的用户 ID 保存为值。

这使得每次搜索都非常非常容易。按少数字段(属性)查询——比如按名字(即“Steve”)和姓氏(即“l:Anything”)仍然很容易——首先从“f:Steve”获取用户 ID 列表,然后从“l :Anything",找到交叉的用户 ID,然后就可以了。

问题(而且有很多):

  1. 保存、更新、删除用户很痛苦。它必须是原子的和一致的操作。此外,如果我们将价值大小限制在某个值上——那么我们就有(潜在的)麻烦。这里真的没有答案。只压缩用户 ID 列表?不过也不算太酷。

  2. 我们要添加新字段以进行搜索的 id。最终。用“城市”说。我们当然可以这样做 "c:Los Angeles" = ..., "c:Chicago" = ...,但是如果我们一开始就没有预见到所有这些“搜索选择”,那么我们将有能够通过所有现有的用户记录创建一些夜间工作或其他东西并为他们更新那些“c:CITY”......相当大的工作!

  3. 锁定问题。用户“u:123”更新了他的名字“Alex”,用户“u:456”更新了他的名字“Alex”。他们都必须用他们的 id 更新“f:Alex”。这意味着要么我们遇到覆盖问题,要么一个更新将等待另一个更新(如果有很多更新,还有成像?!)。

这样做的最佳方法是什么?请记住,我想按多个字段进行搜索?

PS 请,问题是关于 HBase/Cassandra/NoSQL/Key-Value 存储。请 - 不建议使用 MySQL 和“阅读”SELECT;并担心“以后”的扩展问题。我完全按照我的方式问我的问题是有原因的。:-)

4

2 回答 2

4

能够直接查询属性是您在离开 SQL 时失去的功能之一,因此您需要一种方法来维护自己的索引以让您查找记录。

如果您的数据存储没有内置索引或原子列表操作,您将需要处理您提到的锁定问题。但是,索引不一定需要同步 - 维护要重新索引的更新记录队列,并且您有 3 的解决方案,也可以重用于解决 2。

如果特定值的索引列表变得太大而系统无法在单个列表中处理,您可以将用户列表替换为列表列表。但是,如果您有那么多具有相同值的记录,那么它可能无论如何都不是特别有用的搜索条件。

在某些情况下有用的另一个选项是使用单独的系统进行索引 - 例如,您可以设置 lucene 来索引主数据存储中的记录。

于 2010-04-12T04:17:19.427 回答
1

我想我会把它实现为一个 MapReduce 作业,它会按计划运行。每个搜索词都将是一个查找 UID 的行键。

Rowkey:uid1
个人资料:名字:Joe
个人资料:姓氏:Doe
个人资料:昵称:DoeMaster

行键:uid2 个人资料:名字:简 个人资料:姓氏:Doe 个人资料:昵称:SuperBabe



MapReduse 索引所有可搜索的属性,并使用搜索词作为行键添加它们

Rowkey:简
查找:uid:uid2

Rowkey:Doe
查找:uid:uid2,uid1

Rowkey:DoeMaster
查找:uid:uid1

..ETC

现在,如果您需要在用户更改时即时更新索引列表,您可以将更改直接写入索引库,方法是从索引中删除 uid 值并添加到另一个行键。如果同时发生这种情况,可以实施临时锁定。

对于被删除的用户,可以使用告诉用户状态的附加属性将其从搜索中过滤掉。

添加额外的搜索词并不难,因为它只是关于您要索引的名称:值。您还可以通过将类型属性添加到行键/关键字来更多地过滤搜索。即波士顿 - 查找:类型:城市。

这个想法是在 hbase 中维护自己的基于行键的搜索索引。

于 2011-11-15T07:26:48.017 回答