couchbase 4.0 中的组合键查询

Composite key querying in couchbase 4.0

我看到了这样的景色:

function (doc, meta) {
  if(doc.type){
    var id = doc.id ? doc.id: "";
    var company = doc.company ? doc.company: "";
    var store = doc.store ? doc.store: "";

    emit([doc.type, id, company, store]);
  }
}

以及所有包含一个类型和其他 3 个字段组合的文档,具体取决于类型。 我想通过此视图使用以下函数进行一般查询:

def find_by_type_pageing_by_id_company_store(self, format_function=None, page=None, rows=None, recent=None, type=None, id="", company="", store="", include_docs=True):

    if not type:
        logger.error("No Type Provided in find by type query")
        raise exceptions.InvalidQueryParams("No Type Provided in find by type query")

    view = VIEW_BY_TYPE_VIN_COMPANY_STORE

    cb = self.get_cb_bucket()

    query = Query()

    # 'recent' and 'rows' are equivalent and will be unified to 'limit' here
    if recent and rows:
        raise exceptions.InvalidQueryParams(detail="Query may not contain both 'recent' and 'rows'")
    limit = rows or recent

    if limit:
        try:
            rows_per_page = int(limit)
        except ValueError:
            raise exceptions.InvalidQueryParams(detail="Query params 'recent' and 'rows' have to be integers")

        if rows_per_page > settings.PAGINATION_MAX_ROWS_LIMIT:
            raise exceptions.InvalidQueryParams(detail="Query params 'recent' and 'rows' may not exceed %s. "
                                                "Use the additional param 'page=2', 'page=3', etc. to access "
                                                "more objects" % settings.PAGINATION_MAX_ROWS_LIMIT)
        try:
            page = 1 if page is None else int(page)
        except ValueError:
            raise exceptions.InvalidQueryParams(detail="Query param 'page' has to be an integer")

        skip = rows_per_page * (page - 1)

        query.limit = rows_per_page
        query.skip = skip

    query.mapkey_range = [
        [type, id, company, workshop],
        [type, id + query.STRING_RANGE_END, company + query.STRING_RANGE_END, store + query.STRING_RANGE_END]
    ]

    rows = cb.query(view['doc'], view['view'], include_docs=include_docs, query=query)

    if format_function is None:
        format_function = self.format_function_default

    return_array = format_function(rows)
    return return_array

仅查询特定类型或类型和 id 范围时,它可以完美地工作。

但是如果我想把一个公司的某个类型的所有文档,不考虑id和store,其他公司的文档也都送了。

我试过:

query.mapkey_range = [
    ["Vehicle", "", "abc", ""]
    ["Vehicle", q.STRING_RANGE_END, "abc", q.STRING_RANGE_END]
]

我知道,复合键中值的顺序很重要,这就是查询 id 范围可能成功的原因。

但我找不到任何详细说明订单的重要性以及如何处理此用例。

有什么想法或提示可以解决这个问题吗? 提前谢谢你。

对于复合键,emit 中的顺序决定了索引的内部 "sorting"。使用范围查询时,使用此顺序。

你的情况:

  • 索引包含所有车辆
  • 然后所有车辆按 id 排序
  • 对于每个相似的 id,车辆按公司排序
  • 对于每个相似的 ID 和公司,车辆然后按商店排序

我们以4辆车为例。这是索引的样子:

Vehicle,a,ACME,store100
Vehicle,c,Whosebug,store1001
Vehicle,d,ACME,store100
Vehicle,e,Whosebug,store999

这是范围查询发生的情况:

  • 视图引擎从您的范围中找到 >= 到 startKey 的第一行
  • 然后它会找到 <= 您范围的 endKey 的最后一个
  • 它returns 数组中的每一行

您可以看到,根据 ID,这可能会导致看似糟糕的结果:对于 [["Vehicle", "", "ACME", ""], ["Vehicle", RANGE_END, "ACME", RANGE_END]],情况如下:

  • 第 1 行 (a) 被识别为最低匹配 startKey
  • 第 4 行 (e) 与 endKey 不匹配,因为 "Vehicle,e,Whosebug,store999" 由于第三个组件而大于 "Vehicle,RANGE_END,ACME,RANGE_END"
  • 第 3 行(d是上限Vehicle <= Vehicle, d <= RANGE_END, ACME <= ACME, store100 <= RANGE_END
  • 因此返回第 1-3 行,包括来自 "Whosebug"
  • 的第 2 行

TL/DR: emit 中的顺序很重要,不能用复合键左侧的稀疏 "jokers" 进行查询。

将映射函数更改为 emit(doc.type, doc.company, doc.store, id)(最通用到最不通用的属性),相应地修改查询后它应该可以正常工作。

这是文档中的 link,解释了带日期的复合键和范围:Partial Selection With Compound Keys

您有两个选项可以通过 number/order 个字段的变量查询文档:

  1. 使用多维视图(又名空间视图),它允许您在查询中省略部分复合键。以下是使用此类视图的示例:http://developer.couchbase.com/documentation/server/4.0/views/sv-example2.html
  2. 使用 N1QL,它可以让您实际动态查询任意数量的字段。确保为要查询的字段添加索引,并使用 EXPLAIN 语句检查查询是否按预期执行。以下是如何在 Python 中使用 N1QL:http://developer.couchbase.com/documentation/server/4.0/sdks/python-2.0/n1ql-queries.html

正如您已经发现的那样,您不能使用常规视图,因为您只能通过复合键中字段的确切顺序来查询它。