1

我想查询多个候选人以查找可能看起来像"My sear foo"的搜索字符串。现在我想查找具有包含一个(或多个)输入字符串(被空格分隔)的字段的文档。

我找到了一些代码,可以让我按模式进行搜索:

@View(name = "find_by_serial_pattern", map = "function(doc) { var i; if(doc.serialNumber) { for(i=0; i < doc.serialNumber.length; i+=1) { emit(doc.serialNumber.slice(i), doc);}}}")
public List<DeviceEntityCouch> findBySerialPattern(String serialNumber) {
    String trim = serialNumber.trim();

    if (StringUtils.isEmpty(trim)) {
        return new ArrayList<>();
    }
    ViewQuery viewQuery = createQuery("find_by_serial_pattern").startKey(trim).endKey(trim + "\u9999");

    return db.queryView(viewQuery, DeviceEntityCouch.class);
}

这对于寻找一种模式非常有用。但是我如何修改我的代码以在 doc.serialNumber 上获得多个包含?

编辑: 这是当前的解决方法,但我想一定有更好的方法。也只有 OR 逻辑。因此,条目适合 term1 或 term2 在列表中。

@View(name = "find_by_serial_pattern", map = "function(doc) { var i; if(doc.serialNumber) { for(i=0; i < doc.serialNumber.length; i+=1) { emit(doc.serialNumber.slice(i), doc);}}}")
public List<DeviceEntityCouch> findBySerialPattern(String serialNumber) {
    String trim = serialNumber.trim();

    if (StringUtils.isEmpty(trim)) {
        return new ArrayList<>();
    }

    String[] split = trim.split(" ");

    List<DeviceEntityCouch> list = new ArrayList<>();
    for (String s : split) {
        ViewQuery viewQuery = createQuery("find_by_serial_pattern").startKey(s).endKey(s + "\u9999");
        list.addAll(db.queryView(viewQuery, DeviceEntityCouch.class));
    }

    return list;
}
4

1 回答 1

0

看起来您正在这里实现全文搜索。这在 CouchDB 中不会非常有效(我想这同样适用于其他数据库)。

如果我错了,请纠正我,但是从查看您的代码看来,您正在尝试在序列号列表中搜索模式。如果您可以以某种方式索引您将要搜索的数据,CouchDB(或任何其他数据库)将非常有效。否则,您必须获取每条记录并对其执行字符串比较。

我能想到的在 CouchDB 中优化它的唯一方法是如下(有假设):

  1. 您的序列号不是很长(比如 20 个字符?)
  2. 您强制搜索始终为 5 个字符
  3. 生成从您的序列号发出每一个 5 字符长的子字符串的视图 - 或多或少(可以优化,不确定我是否得到了):

    ...
    for (var i = 0; doc.serialNo.length > 5 && i < doc.serialNo.length - 5; i++) {
        emit([doc.serialNo.substring(i, i + 5), doc._id]);
    }
    ...
    
  4. 使用_countreduce函数

现在是以下网址:

http://localhost:5984/test/_design/serial/_view/complex-key?startkey=["01234"]&endkey=["01234",{}]&group=true

将返回一个文档列表,其中一个键的命中计数为01234. 如果您不分组并将 reduce 选项设置为 false,您将获得所有匹配项的列表,如果单个文档有多个匹配项,则包括重复项。有关复杂键查找的信息,请参阅http://ryankirkman.com/2011/03/30/advanced-filtering-with-couchdb-views.html

我不确定 couchdb 在更新该视图方面的效率如何。这取决于您将拥有多少条记录以及在查询视图之间出现多少新条目(我了解 couchdb 会按需重建视图的 b-tree)。

我已经生成了一个这样的视图,它将文档 ID 拆分为 5 个字符长的键。在超过 1K 的文档中,它生成了超过 30K 的结果 - id 是 32 字符长,简单的数学真的:(serialNo.length - searchablekey.length + 1) * docscount)。生成视图需要一段时间,但查找速度很快。

您可以生成多种长度的键,等等。一切都取决于您的记录数与查找速度。

于 2016-05-12T02:59:37.993 回答