我得到了这样的观点:
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和商店,也提供其他公司的文档。
我试过:
query.mapkey_range = [
["Vehicle", "", "abc", ""]
["Vehicle", q.STRING_RANGE_END, "abc", q.STRING_RANGE_END]
]
我知道,复合键中值的顺序很重要,这就是为什么查询id范围可能是成功的。
但我找不到任何详细的解释,该命令如何重要以及如何处理这个用例。
有任何想法或提示如何应对这个问题? 提前谢谢。
答案 0 :(得分:1)
使用复合键,emit
中的顺序决定内部"排序"的索引。使用范围查询时,将使用此订单。
在你的情况下:
让我们举一个4辆车的例子。这是索引的样子:
Vehicle,a,ACME,store100
Vehicle,c,StackOverflow,store1001
Vehicle,d,ACME,store100
Vehicle,e,StackOverflow,store999
以下是范围查询会发生的情况:
您可以看到,根据ID,这会导致看似糟糕的结果:对于[["Vehicle", "", "ACME", ""], ["Vehicle", RANGE_END, "ACME", RANGE_END]]
,会发生以下情况:
a
)被标识为与startKey匹配的最低值e
)与endKey 不匹配,因为"Vehicle,e,StackOverflow,store999"
由于第三个组件而大于"Vehicle,RANGE_END,ACME,RANGE_END"
d
)是上限:Vehicle <= Vehicle, d <= RANGE_END, ACME <= ACME, store100 <= RANGE_END
TL / DR :在排序事项中排序,您无法使用稀疏&#34; jokers&#34;在复合键的左侧。
将地图功能更改为emit(doc.type, doc.company, doc.store, id)
(最常用到最不通用的属性),并且在您相应地重新编写查询后它应该可以正常工作。
以下是解释复合键和日期范围的文档的链接:Partial Selection With Compound Keys
答案 1 :(得分:1)
您可以通过可变数量/字段顺序查询文档有两个选项:
正如您已经发现的那样,您无法使用常规视图,因为您只能按复合键中字段的确切顺序查询。