使用 IBM Cloudant 查询常见问题解答
IBM® Cloudant® for IBM Cloud® Query 是一个 API ,用于根据数据库的文档属性值来查询数据片。 它是一个灵活的 API ,必须谨慎使用,以确保随着时间的推移,随着数据大小的增长,可以保持数据库性能。
如何使用 IBM Cloudant 查询?
IBM Cloudant 通过在 HTTP POST 主体中传递查询的 JSON 规范的 POST /{db}/_find
API 端点来访问查询。 例如,此查询最多可找到 10 个文档,其中 firstname
是 "Charles" , surname
是
"Dickens":
{
"selector": {
"firstname": "Charles",
"surname": "Dickens"
},
"limit": 10
}
有关更多信息,请参阅 选择器语法。
如何创建索引以支持 IBM Cloudant 查询?
如果没有合适的辅助索引,那么 IBM Cloudant 查询会依次扫描数据库中的每个文档,直到它具有足够的匹配项来满足查询。 数据集越大,要扫描以查找匹配文档的文档越多,响应时间越慢。 为了提高性能, IBM Cloudant 查询 _find
必须由合适的辅助索引支持。 辅助索引是预先计算的数据结构,允许 IBM Cloudant 在不扫描不相关文档的情况下快速跳至所需的数据片。 对于 surname
字段,我们调用
POST /{db}/_index
端点以将 JSON 索引定义作为 HTTP POST 主体传递:
{
"index": {
"fields": ["firstname", "surname"]
},
"ddoc": "jsonindexes",
"name": "byName",
"type": "json"
}
有关更多信息,请参阅 创建索引。
我能否使用 IBM Cloudant 查询对搜索结果进行排序?
是的! _find
JSON 语法允许提供 sort
参数,以列出要作为排序依据的一个或多个属性。 在这种情况下,我们将按 date
进行排序:
{
"selector": {
"firstname": "Charles",
"surname": "Dickens"
},
"sort": ["date"],
"limit": 10
}
必须存在包含 selector
字段和 sort
字段的合适索引。 否则, IBM Cloudant 将拒绝执行查询。 下面显示了先前查询的合适索引定义:
{
"index": {
"fields": [
"firstname",
"surname",
"date"
]
},
"ddoc": "jsonindexes",
"name": "byNameAndDate",
"type": "json"
}
我可以按反向顺序排序吗?
是! IBM Cloudant 查询支持按升序或降序对结果集进行排序,但不支持两者的组合。 例如,按升序对某些字段进行排序的查询,以及不允许降序的查询。
此查询将返回与 firstname
和 surname
匹配的文档,并按 surname
/firstname
/date
降序排序:
{
"selector": {
"firstname": "Charles",
"surname": "Dickens"
},
"sort": [
{ "firstname": "desc" },
{ "surname": "desc" },
{ "date": "desc" }
],
"limit": 10
}
必须存在包含 selector
字段和 sort
字段的合适索引。 否则, IBM Cloudant 将拒绝执行查询。 下面显示了先前查询的合适索引定义:
{
"index": {
"fields": [
"firstname",
"surname",
"date"
]
},
"ddoc": "jsonindexes",
"name": "byNameAndDate",
"type": "json"
}
上一个索引适用于升序和降序排序顺序。
如何判断索引是否支持查询?
POST /{db}/_explain
API 端点在传递通常发送到 POST /{db}/_find
端点的 JSON 对象时,说明如何处理此类查询以及可以使用哪些索引
(如果有)。
如果响应中的 index
对象指示正在使用 "all_docs" ,那么需要完整数据库扫描才能为查询提供服务。 建议您使用 _explain
机制来检查每个 IBM Cloudant 查询,以确保在部署到生产之前使用索引。
例如, firstname
, surname
和 date
上的 type=json
索引适用于查找以下对象的文档:
- 已知的
firstname
,lastname
和date
。 - 已知
firstname
,lastname
和一系列date
值 (使用$lt
,$lte
,$gt
和$gte
运算符)。 - 已知
firstname
和lastname
按date
排序。
它还可用于帮助查询 firstname
, surname
, date
和其他属性。 换言之,它可能只能回答部分查询,但可以帮助减少扫描以查找答案的文档数。
如何确保查询有效?
理想情况下, IBM Cloudant 查询执行仅需要扫描一个文档以查找返回的每个文档。 如果查询必须为返回的每个文档扫描一百万个文档,那么它显然不是最佳的,并且需要辅助索引来帮助。
执行查询时,将 execution_stats: true
作为额外参数传递会强制 IBM Cloudant 枚举它在执行查询时扫描的文档数,例如:
{
"selector": {
"firstname": "Charles",
"surname": "Dickens"
},
"sort": ["date"],
"limit": 10,
"execution_stats": true
}
返回的数据现在包含额外的 JSON 对象:
{
...
"execution_stats": {
"total_keys_examined": 0,
"total_docs_examined": 1000000,
"total_quorum_docs_examined": 0,
"results_returned": 2,
"execution_time_ms": 4400.699
}
}
total_docs_examined
与 results_returned
之间的比率在此处至关重要: 高值指示针对返回的每个文档扫描的文档数过多。
有关更多信息,请参阅 有关优化 IBM Cloudant 查询的博客帖子。
哪些 IBM Cloudant 查询运算符无法使用索引?
除 $and
以外的任何 组合运算符 都可以执行查询以执行完全数据库扫描,而无需辅助索引的帮助。 例如,如果使用 $or
运算符,那么不能使用辅助索引来帮助查询。 如果有疑问,请使用 POST /{db}/_explain
端点来检查是否使用了索引,并使用 execution_stats: true
参数来度量每个查询的效率。
要使 type=json
索引用于支持查询,它必须与选择器和排序参数中使用的字段匹配。 可以在最后一个元素上使用比较运算符来执行 范围查询。
有关更多信息,请参阅 说明计划。
我能否将 IBM Cloudant 查询与 Lucene 索引配合使用?
是! IBM Cloudant 查询支持两种类型的索引:
"type": "json"
-由 IBM Cloudant的 MapReduce API 提供支持的固定顺序索引。 适用于与索引中的每个术语匹配的固定样板查询。"type": "text"
-由 IBM Cloudant的搜索 API 提供支持的 Lucene 索引。 适用于跨一个,部分或所有已建立索引的字段的通用查询。
将使用如下所示的索引定义创建 type=text
索引:
{
"index": {
"fields": [
{ "name": "firstname", "type": "string"},
{ "name": "surname", "type": "string"},
{ "name": "date", "type": "string"}
]
},
"ddoc": "textindexes",
"name": "byNameAndDate",
"type": "text"
}
请注意, fields
数组要求对每个属性进行命名和输入 (与 type=json
索引不同)。
结果索引可由包含一个或多个已建立索引的字段的查询使用:
{
"selector": {
"surname": "Dickens"
},
"sort": ["date"],
"limit": 10,
"execution_stats": true
}
与 type=json
索引相比, Lucene 支持的索引允许一些额外的灵活性。 您可以按任何顺序使用一个,部分或所有已建立索引的字段,并且索引支持查询。 使用 type=json
索引时,查询必须与所有已建立索引的字段匹配才能有用。
有关更多信息,请参阅 创建 type=text
索引。
能否为数据库子集创建 IBM Cloudant 查询索引?
是的! 如果您的用例要求在数据库子集 (例如, 已完成 订单, 已确认 用户或 库存 产品) 的范围内执行查询,那么最好使用 部分索引 。 部分索引允许在索引构建时使用 IBM Cloudant 查询选择器,以将使其进入索引的数据集回温,从而使索引保持小而高性能。 然后,在查询时,将使用标准 IBM Cloudant 查询选择器来进一步过滤部分索引以获取结果集。
通过将 partial_filter_selector
传递到 POST /{db}/_index
方法来创建 partial 索引。 在此示例中,只有状态为 "已发布" 或 "重新打印" 的硬背书才会使其成为索引。 请参阅以下示例:
{
"index": {
"partial_filter_selector": {
"$or": [
{ "status": "published" },
{ "status": "reprint" }
],
"hardback": true
},
"fields": ["firstname","surname","date"]
},
"ddoc" : "partialindexes",
"name": "byNameAndDate"
"type" : "json"
}
在查询时,必须提供 use_index
字段以告知 IBM Cloudant 您希望它使用指定的索引:
{
"selector": {
"$or": [
{ "status": "published" },
{ "status": "reprint" }
],
"hardback": true,
"firstname": "Charles",
"surname": "Dickens"
},
"sort": ["date"],
"limit": 10,
"execution_stats": true,
"use_index": "partialindexes/byNameAndDate"
}
partial_filter_selector
字段在查询时间选择器中重复。
有关更多信息,请参阅 创建部分索引。
能否在分区数据库上使用 IBM Cloudant 查询?
是的! 缺省情况下, IBM Cloudant 查询索引为 全局 (例如,未分区) ,但在 _分区数据库_上,可以通过在创建索引时添加 partitioned: true
来创建 分区索引 : e 要在 firstname
和 surname
上创建分区索引,请使用 POST /<dbname>/_index
:
{
"index": {
"fields": ["firstname", "surname"]
},
"ddoc": "jsonindexes",
"name": "byName",
"type": "json",
"partitioned": true
}
当您仅运行分区查询 (例如,通过使用 GET /<dbname>/_partition/<partition key>/_find
API 端点) 时,可以使用分区索引。
有关更多信息,请参阅 创建分区索引。
我可以在查询中使用正则表达式吗?
是! IBM Cloudant 查询具有允许查询中的正则表达式词汇的 $regex 运算符 。
继续谨慎操作: 如果查询 仅 包含一个 $regex
运算符,那么辅助索引无法帮助您-该查询将生成数据库的逐文档扫描。
可以将 $regex
运算符标记到已执行的查询的末尾。 例如,如果在 firstname
和 surname
上已有 type=json
索引,那么可以使用以下示例:
{
"selector": {
"firstname": "Charles",
"surname": "Dickens",
"title": {
"$regex": "^Oliv"
}
},
"limit": 10
}
IBM Cloudant 使用索引通过 firstname
和 surname
查找文档,并在 title
字段上选择使用正则表达式的结果集。