如何在 CouchDB 上执行参数化查询

Posted

技术标签:

【中文标题】如何在 CouchDB 上执行参数化查询【英文标题】:How do I perform a parameterized query on CouchDB 【发布时间】:2010-11-15 05:47:50 【问题描述】:

我想使用 CouchDB 为我存储一些数据,然后使用 RESTful api 调用来获取我需要的数据。我的数据库称为“test”,我的文档都有类似的结构,看起来像这样(其中 hello_world 是文档 ID):

"hello_world" : "id":123, "tags":["hello", "world"], "text":"Hello World"
"foo_bar" :"id":124, "tags":["foo", "bar"], "text":"Foo Bar" 

我想做的是让我的用户发送一个查询,例如:“给我所有包含‘hello world’的文档。我一直在玩视图,但是看起来他们只允许我将这些值中的一个或多个移动到 map 函数的“关键”部分。这使我能够执行以下操作:

http://localhost:5984/test/_design/search/_view/search_view?key="你好"

但这不允许我让我的用户指定他们的查询字符串。例如,如果他们搜索“hello world”会怎样。我必须做两个查询:一个用于“hello”,一个用于“world”,然后我必须编写一堆 javascript 来组合结果、删除重复项等(YUCK!)。我真正想要的是能够做这样的事情:

http://localhost:5984/test/_design/search/_view/search_view?term="你好世界"

然后在视图 map/reduce 函数中使用参数“hello world”,在 tags 数组中查找所有同时包含“hello”和“world”的文档。使用 CouchDB 甚至可以实现这种事情吗?是否有另一种方法可以在我没有想到的视图中完成此操作?

【问题讨论】:

【参考方案1】:

CouchDB 视图不支持分面搜索或全文搜索或结果交集。 couchdb-lucene 插件可以让你做所有这些事情。

http://github.com/rnewson/couchdb-lucene/tree/master

【讨论】:

想详细说明或提供示例? 他是该项目的开发者之一——“你做不到,但这个项目会让你。”这是一个很好的答案。【参考方案2】:

从技术上讲,如果您为每个文档发出文档标签的每组 powerset 作为键,这是可能的。键集元素必须是有序的,您的查询也必须查询有序的标签。

function map(doc) 
  function powerset(array)  ... 

  powerset_of_tags = powerset(doc.tags)
  for(i in powerset_of_tags) 
    emit(powerset_of_tags[i], doc);
  

对于文档"hello_world" : "id":123, "tags":["hello", "world"], "text":"Hello World",这将发出:

 key: [], doc: ... 
 key: ['hello'], doc: ... 
 key: ['world'], doc: ... 
 key: ['hello', 'world'], doc: ... 

虽然这是可能的,但我认为这是一个相当棘手的解决方案。我不想想象更多标签的视图的磁盘使用情况。我预计发出的密钥数量会增长到 2^n。

【讨论】:

不建议这样做。性能将受到很大影响,正如您提到的那样,索引的存储将失控。上面提到的 couchdb-lucene 是做他想做的事情的正确方法。【参考方案3】:

在底层,couchdb 通过 b-tree 存储数据,因此您应该使用视图进行预处理,这种情况下的限制是您无法搜索正则表达式。或者,您可以通过视图中的键的前缀或后缀进行搜索。

注意:不要使用emit(key, doc),它会克隆文档,你应该使用emit(key, null)或emit(key)并在查询时添加“include_docs = true”。

您可以使用您的标签作为查询关键字。

//查看函数

function (doc) 
  if (doc.type === "hello") 
    emit(doc);
  

//芒果查询

db
.query(your_view_name,
       startkey: startkey, endkey: endkey, include_docs: true );

注意:

endkey = startkey + "\uffff";
startkey = "h", "he", "hell"...

另外:如果您不希望性能下降,永远不要使用芒果查询来查询正则表达式,sences。我通过查看功能将性能问题从 2 分钟缩短到 2 秒。

【讨论】:

以上是关于如何在 CouchDB 上执行参数化查询的主要内容,如果未能解决你的问题,请参考以下文章

如何使用参数化查询提高Cypher查询的性能

如何在 C# 中创建动态参数化 SQL 查询字符串

在带有 PDO 的 PHP 中,如何检查最终的 SQL 参数化查询? [复制]

在带有 PDO 的 PHP 中,如何检查最终的 SQL 参数化查询? [复制]

如何正确使用 PDO 对象进行参数化 SELECT 查询

如何安全地为 bigquery 节点插入转义用户输入?可以在 bigquery.insert 节点库上使用参数化查询吗?