IBM Cloud Docs
使用 IBM Cloudant 查询常见问题解答

使用 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 查询支持按升序或降序对结果集进行排序,但不支持两者的组合。 例如,按升序对某些字段进行排序的查询,以及不允许降序的查询。

此查询将返回与 firstnamesurname 匹配的文档,并按 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 查询,以确保在部署到生产之前使用索引。

例如, firstnamesurnamedate 上的 type=json 索引适用于查找以下对象的文档:

  • 已知的 firstnamelastnamedate
  • 已知 firstnamelastname和一系列 date 值 (使用 $lt$lte$gt$gte 运算符)。
  • 已知 firstnamelastnamedate排序。

它还可用于帮助查询 firstnamesurnamedate和其他属性。 换言之,它可能只能回答部分查询,但可以帮助减少扫描以查找答案的文档数。

如何确保查询有效?

理想情况下, 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_examinedresults_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 要在 firstnamesurname上创建分区索引,请使用 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 运算符标记到已执行的查询的末尾。 例如,如果在 firstnamesurname上已有 type=json 索引,那么可以使用以下示例:

{
  "selector": {
    "firstname": "Charles",
    "surname": "Dickens",
    "title": {
      "$regex": "^Oliv"
    }
  },
  "limit": 10
}

IBM Cloudant 使用索引通过 firstnamesurname 查找文档,并在 title 字段上选择使用正则表达式的结果集。