查询复杂键中的ANY值(AKA通配符)

时间:2018-08-16 11:46:01

标签: couchdb

我经历了文档和SO问题,但没有找到针对我的特殊情况的明确答案。

具有这种复杂的(发射阵列)键映射功能

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

我想用一些值为空的查询它-因此查询可以接受键中的 ANY 值,即

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

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

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

但无济于事-没有行..

4 个答案:

答案 0 :(得分:2)

使用单个索引是不可能的。您只能对键的第一部分进行子键搜索。为了满足您的需求,您将需要多个索引-根据您需要支持的查询的复杂程度,您可能需要大量的索引。

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

为支持按姓氏搜索,您可以反转索引-或仅对 姓氏进行索引。

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

答案 1 :(得分:1)

在沙发数据库查询中无法使用“ Any_value”通配符(但是,对开发人员的问题-为什么不行?),因此执行具有空(= accept_any)值的多维查找的唯一方法是维护所有可能的索引非空搜索值的组合。我最终得到了这个_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}
      }
    };

其中(即已知的MiddleName和lastName)映射函数如下所示:

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

然后我可以根据已知的数据集查询相应的视图。

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

感谢所有响应者,您的帮助无价。

答案 2 :(得分:0)

每个文档可以发出多个索引条目。为了解决您的简单示例,您可以创建一个像这样的索引:

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”,因此如果您的搜索专门针对Lastname =“ Mozart”,则返回假阳性。

答案 3 :(得分:0)

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”的任何文档。

相对于先前的建议,这样做的优点是您不会从名字或中间名也是莫扎特的文档中得到误报。