如何在CouchDB中创建“like”过滤器视图

z9gpfhce  于 2022-12-09  发布在  CouchDB
关注(0)|答案(7)|浏览(199)

下面是我在sql中需要的示例:
SELECT名称FROM雇员WHERE名称LIKE**%兄弟%**
如何在CouchDB中创建这样的视图?

d6kp6zgx

d6kp6zgx1#

简单的答案是CouchDB视图并不适合这种情况。
更复杂的答案是,这种类型的查询在典型的SQL引擎中也往往效率非常低,因此,如果您承认 * 任何 * 解决方案都会有折衷,那么CouchDB实际上具有允许您选择折衷的好处。
1.SQL方法
当您执行SELECT ... WHERE name LIKE %bro%时,我所熟悉的所有SQL引擎都必须执行所谓的“全表扫描”,这意味着服务器读取相关表中的每一行,并对字段进行暴力扫描以查看是否匹配。
您可以在CouchDB 2.x中使用$regex操作符对Mango查询执行此操作。

{"selector":{
  "name": {
    "$regex": "bro"
  }
}}

似乎没有提供任何区分大小写等选项,但您可以扩展它,使其仅匹配开头/结尾或更复杂的模式。如果您还可以通过其他(可索引的)字段操作符来限制查询,这可能有助于提高性能。正如文档中所警告的:
正则表达式不适用于索引,所以不应该用它们来过滤大型数据集。[...]
您也可以在CouchDB 1.x中使用临时视图进行完全扫描:

POST /some_database/_temp_view

{"map": "function (doc) { if (doc.name && doc.name.indexOf('bro') !== -1) emit(null); }"}

这将遍历数据库中的每一个文档,并给予你一个匹配文档的列表。你可以调整map函数来匹配文档类型,或者用一个特定的排序键-emit(doc.timestamp)-或者一些对你的目的有用的数据值-emit(null, doc.name)来发出。
2.“大量可用磁盘空间”方式
根据源数据的大小,您可以创建一个索引,该索引发出每个可能的“内部字符串”作为其永久(磁盘上)视图关键字。也就是说,对于“Dobros”这样的名称,您可以使用emit("dobros"); emit("obros"); emit("bros"); emit("ros"); emit("os"); emit("s");。对于“%bro%”这样的术语,您可以使用startkey="bro"&endkey="bro\uFFFF"查询视图,以获取该查找术语的所有匹配项。您的索引将近似于文本内容的大小 * squared*,但是如果你需要做一个任意的“find in string”,比上面的完全DB扫描更快,并且有足够的空间,这可能会起作用。
这也给我们带来了...
3.全文搜索方式
您可以使用CouchDB插件(couchdb-lucene现在通过Dreyfus/Clouseau for 2.x、ElasticSearchSQLite's FTS)为文档生成一个辅助的面向文本的索引。
请注意,大多数全文搜索索引也不支持任意通配符前缀,可能是出于类似的空间效率原因。通常全文搜索并不意味着“蛮力二分搜索”,而是“单词搜索”。YMMV尽管如此,还是看看全文引擎中可用的选项吧。
如果你不需要在字段的任何地方找到“bro”,你可以用常规的CouchDB视图实现基本的“find a word started with X”搜索,只需要在不同的特定于区域的单词分隔符上进行拆分,并省略这些“单词”作为视图键。这将比上面的方法更高效,并与索引的数据量成比例地扩展。

uz75evzq

uz75evzq2#

不幸的是,使用LIKE %...%进行搜索实际上并不是CouchDB视图的工作方式,但是您可以通过安装couchdb-lucene来实现大量的搜索功能,它是一个全文搜索引擎,可以在数据库上创建索引,您可以使用它进行更复杂的搜索。
在没有任何第三方工具的情况下,在数据库中“搜索”给定键的典型方法是创建一个视图,将您要查找的值作为键发出。在您的示例中:

function (doc) {
    emit(doc.name, doc);
}

这将输出数据库中所有名称的列表。
现在,你将根据你键的第一个字母来“搜索”。例如,如果你正在搜索以“bro”开头的名字。

/db/_design/test/_view/names?startkey="bro"&endkey="brp"

注意,我取了search参数的最后一个字母,并“递增”了其中的最后一个字母。同样,如果您想执行搜索,而不是聚集统计信息,您应该使用像lucene这样的全文搜索引擎。

du7egjpx

du7egjpx3#

您可以使用正则表达式。根据此表,您可以编写如下代码来返回任何包含“SMS”的ID。

{
   "selector": {
      "_id": {
         "$regex": "sms"
      }
   }
}

可以在上使用的基本正则表达式包括

"sms$" roughly to LIKE "%sms"
"^sms" roughly to LIKE "sms%"

你可以阅读更多关于正则表达式here

ubby3x7f

ubby3x7f4#

我发现了一个简单的查看代码为我的问题...
{
“获取可用产品”:
{“Map”:“函数(doc){
变量前缀= doc ['产品ID'].match(/[A-Za-z 0 -9]+/g);
if(前缀)
(前缀中的变量pre){ emit(前缀[pre],null);}
}”

}
从这个Angular 看代码如果我把一个关键句拆分成一个关键词...
?key="[搜索关键字]"
但是我需要更复杂代码,因为如果我运行这个代码,我只能找到我键入的单词(例如:吃、食物等)。
但是如果我想键入不是完整单词(例如:eat中ea,或foo中的food)代码不起作用。

soat7uwm

soat7uwm5#

我知道这是个老问题,但是:使用“list”函数怎么样?您可以拥有所有普通视图,然后在设计文档中添加“list”函数来处理视图的结果:

{
  "_id": "_design/...",
  "views": {
    "employees": "..."
  },
  "lists": {
    "by_name": "..."
  }
}

而附加到“by_name”函数的函数,应该是这样的:

function (head, req) {
  provides('json', function() {
    var filtered = [];

    while (row = getRow()) {
      // We can retrive all row information from the view
      var key = row.key;
      var value = row.value;
      var doc = req.query.include_docs ? row.doc : {};

      if (value.name.indexOf(req.query.name) == 0) {
        if (req.query.include_docs) {
          filtered.push({ key: key, value: value, doc: doc});
        } else {
          filtered.push({ key: key, value: value});
        }
      }
    }

    return toJSON({ total_rows: filtered.length, rows: filtered });
  });
}

当然,你也可以使用正则表达式。这不是一个完美的解决方案,但对我来说很有效。

deyfvvtc

deyfvvtc6#

你可以像正常一样发出你的文档。emit(doc.name, null);我会在name上抛出一个toLowerCase()来消除大小写敏感性。
然后用一系列键查询视图,看看是否显示了“类似”查询的内容。

keys = differentVersions("bro"); // returns ["bro", "br", "bo", "ro", "cro", "dro", ..., "zro"]
$.couch("db").view("employeesByName", { keys: keys, success: dealWithIt } )

一些注意事项
1.很明显,这个数组会很快变得很大,这取决于differentVersions返回的内容。你可能会在某个时候达到post数据限制,或者可能会得到很慢的查找。
1.结果只能像differentVersions一样让你猜出这个人想要拼写什么。显然,这个函数可以简单也可以复杂。在这个例子中,我尝试了两种策略,a)删除一个字母并按下它,以及B)用所有其他字母替换位置n处的字母。因此,如果有人一直在寻找“bro”,但键入了“gro”或“bri”甚至“bgro”,differentVersions会在某个时候将其置换为“bro”。
1.虽然不是理想的,它仍然是相当快的,因为在沙发的b树查找是快速的。

r1wp621o

r1wp621o7#

为什么不能直接在view中使用indexOf()呢?

相关问题