【问题标题】:Ektorp CouchDb: Query for pattern with multiple containsEktorp CouchDb:查询具有多个包含的模式
【发布时间】:2016-05-11 20:21:52
【问题描述】:

我想查询多个候选人,以查找可能类似于 “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;
}

【问题讨论】:

    标签: java search couchdb ektorp


    【解决方案1】:

    看起来您正在这里实现全文搜索。这在 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)。 生成视图需要一段时间,但查找速度很快。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多