查询复杂键中的任何值(也称为通配符)

Query for ANY value in complex key (AKA wildcard)

我查看了文档和 SO 问题,但没有找到适合我的特定案例的任何明确答案。

视图中有这个复杂的(发射数组)键映射函数

function(doc) {
    if (doc.userFirstName && doc.userLastName && doc.userGender && doc.homeCountry && doc.homeCity) {
      emit([
        doc.userFirstName,
        doc.userMiddleName,
        doc.userLastName,            
      ], null)
    }

我想用其中一些为空的值来查询它 - 所以查询可以接受键中的 任何 值,即

userFirstName = *anyvalue*
userMiddleName = *anyvalue*
userLastName = "Mozart"

如果可能 - 我的 startKey= 和 endKey= 请求参数应该是什么样的? 我试过了

startkey=[{},{},"Mozart"]&endkey=[{},{},"Mozart"]

但无济于事 - 没有行..

您可以为每个文档生成多个索引条目。要解决您的简单示例,您可以创建这样的索引:

function(doc) {
    if (doc.userFirstName && doc.userLastName && doc.userGender && doc.homeCountry && doc.homeCity) {
      emit(doc.userFirstName, null);
      emit(doc.userMiddleName, null);
      emit(doc.userLastName, null);
    }

可以通过简单的索引搜索找到 "Mozart"。我怀疑您的实际要求更复杂 - 例如,名字或中间名也可能是 "Mozart",因此如果您的搜索专门针对姓氏="Mozart",则 return 是误报。

这对于单个索引是不可能的。您只能对密钥的第一部分进行子密钥搜索。为了满足您的需求,您将需要多个索引——并且根据您需要支持的查询的复杂程度,您可能需要大量索引。

为了支持按名字搜索,您示例中的索引就可以了。

为了支持按姓氏搜索,您可以反转索引——或者仅索引姓氏。

如果您需要按中间名搜索,则需要第三个索引。如果您想按名字和姓氏(省略中间名)搜索,您将需要另一个索引等。

"Any_value" 通配符在 couchdb 查询中是不可能的(但是,开发者的问题 - 为什么不呢?),所以执行多维查找的唯一方法是空的 (=accept_any) values 是为非空搜索值的所有可能组合维护索引。我最终得到了这个 _design 文档:

let ddoc = {
      '_id': '_design/search',
      'views': {
        'firstOnly': {'map': firstOnly},
        'middleOnly': {'map': middleOnly},
        'lastOnly': {'map': lastOnly},
        'firstLast': {'map': firstLast},
        'firstMiddle': {'map': firstMiddle},
        'middleLast': {'map': middleLast}
      }
    };

其中(即对于已知的中间名和姓氏)映射函数如下所示:

const middleLast =
  `function(doc) {
    if (doc.userMiddleName && doc.userLastName) {
      emit([
        doc.userMiddleName,
        doc.userLastName,
      ], null)
    }
  }`;

那我是不是可以根据已知的数据集查询对应的视图呢

所以六个复杂的键索引而不是一个。相当繁重(如果有数百万条记录),但不幸的是,这是唯一可能的解决方案。

感谢所有的响应者,你们的帮助是无价的。

一个couchdb索引只有一个顺序;您发出的密钥(整个密钥)。这显然是一种非常简单的索引,但速度也很快。

解决您的问题的一种常用方法如下;

function(doc) {
  if (doc.userFirstName) {
    emit(["firstname", doc.userFirstName], null);
  }
  if (doc.userMiddleName) {
    emit(["middlename", doc.userMiddleName], null);
  }
  if (doc.userLastName) {
    emit(["lastname", doc.userLastName], null);
  }
}

然后您可以使用 ?key=["lastname", "Mozart"].

查询 lastname = "Mozart" 的任何文档

与之前的建议相比,此建议的优点是您不会从名字或中间名也是莫扎特的文档中得到误报。