有没有办法在 CouchDB 中实现多个标签搜索?我有每个带有多个标签的文档(帖子)。我需要找到带有任意一组标签的帖子。我该怎么做?我当然可以通过多次调用视图来完成此操作,该视图为我提供标签的文档,然后在我的应用程序中对其进行排序,但我想知道是否有办法在 CouchDB 视图中实现相同的目的。
6 回答
在较新版本的 CouchDB 中,您可以使用名为 的 JSON 文档 POST 到视图,该文档keys
允许多键查找。结构看起来像这样:
{"keys": ["first_tag", "second_tag", "third_tag"]}
这可以发布到您拥有的视图,该视图正在为其各自的键发出标签。
此处记录了此查询选项和其他查询选项。
我已经解决了这个问题,创建了一个带有递归函数的视图。这里的要点https://gist.github.com/820412
我认为下面应该给你一个稍微复杂但可靠的算法——即它确实可以快速找到第一个结果,即使你有很多文档。它在实践中可能表现不佳:(
按每个标签和文档 ID 索引文档:
[<some tag>, <document id>]
例如对于文档文档
- 带有标签 [blue, green, red] 的 docid1
- 带有标签 [蓝色、黄色] 的 docid2
你得到
['蓝色','docid1'] ['蓝色','docid2'] ['绿色','docid1'] ['红色','docid1'] ['黄色','docid2']
现在,对于您要搜索的每个标签,您都打开从 [tag, ...] 开始的并行搜索。
对于每个标签,您维护一个当前搜索位置。如果所有搜索中的 docid 都匹配,则您找到了匹配项。如果它们不匹配,请尝试通过范围搜索至少跳到最高的文档 ID。重复。
[基本上是一个连接。]
跳过理论上很快:我们有一个索引来查找这些文档。实际上,由于到服务器的所有往返行程,它可能很慢。能够将该算法卸载到服务器上执行的函数会很好。那可能吗?
一种方法是如上面 Ryan Duffield 所解释的。虽然它解决了一些查询,但随着时间的推移它会变得难以管理。其他方法是使用 CouchDB 目前不支持的全文搜索,但有一个使用 Lucene 的外部插件。更多在这里http://wiki.apache.org/couchdb/Full_text_search。
所以,据我了解,答案是否定的。CouchDB 无法查询存在多个标签的文档(使用 lucene 或 mysql 的解决方法不计算在内,这样我们就失去了 CouchDB 的一些功能)。悲伤的消息 :(。
(存在多个标签 - 同时具有 A 和 B,而不是 A 或 B)
更新! 这是可能的,但仅限于 2-3 个标签。
http://wiki.apache.org/couchdb/EntityRelationship
多键查询
一些应用程序需要查看具有多个键的实体的交集。在上面的示例中,这将是对“朋友”和“同事”组中的联系人的查询。处理这种情况最直接的方法是查询其中一个键,然后在客户端按其余键进行过滤。如果键频率变化很大,那么进行初始调用以确定具有最低频率的键并使用它从数据库中获取初始文档列表也是值得的。
如果这不是一个好的选择,则可以对键的组合进行索引,尽管给定文档的索引的增长将随其键的数量呈指数增长。尽管如此,对于小型密钥集,这是一个选项,因为可以对密钥进行排序,并且可以省略作为较大密钥前缀的密钥。例如,对于键集 [1 2 3],可能的键组合是 [1] [2] [3] [1 2] [1 3] [2 3] [1 2 3] 但是,索引只需要包含键 [3] [1 3] [2 3] [1 2 3] 因为(例如)与键 [1 2] 匹配的文档可以通过查询 startkey=[1,2,null] 和 endkey 获得=[1,2,{}] 索引条目的数量将是 2^(n-1) 个键的数量。
最后一种选择是使用单独的索引,例如 couchdb-lucene 来帮助进行此类查询。
实际上,标记似乎是一个非常相关的问题,并且不能很好地与 CouchDB 的设计配合使用。所以我决定在 mysql 上有一个用于标签的小型数据库,并将实际文档存储在 CouchDB 中。这让我两全其美。虽然这种技术在同步方面存在问题,但在标签上搜索是对 sql 的一种高效操作,并且内容不必过多担心复制或分片。感谢您的所有回答。