IBM Cloud Docs
创建选择器表达式

创建选择器表达式

通常,每当您有一个接受自变量的运算符时,该自变量本身可以是另一个具有其自身自变量的运算符。 此扩展支持更复杂的选择器表达式。

当您使用 JSON 类型的索引时,组合或数组逻辑运算符 (例如 $regex) 可能会导致完全数据库扫描,从而导致性能低下。 仅等同性运算符,例如 $eq$gt$gte$lt$lte (但不包括 $ne) 启用索引查找。 要确保有效使用索引,请分析 针对每个查询的 说明计划

大多数选择器表达式的工作方式与您对运算符的期望完全相同。 $regex 运算符使用的匹配算法当前 基于 Perl 兼容正则表达式(PCRE)库。 但是,并非所有 PCRE 库都已实现。 此外, $regex 操作程序的某些部分超出了 PCRE 提供的内容。 有关实现的内容的更多信息,请参阅 Erlang 正则表达式 信息。

排序语法

sort 字段包含字段名称和方向对的列表,表示为基本数组。 第一个字段名称和方向对是最顶级的排序。 如果提供了进一步的对,请指定下一个排序级别。

排序字段可以是任何字段。 如果需要子字段,请使用点分表示法。

方向值为 asc 表示升序,desc 表示降序。

如果排除方向值,那么将使用缺省值 asc

请参阅以下简单排序语法示例:

[
	{
		"fieldName1": "desc"
	},
	{
		"fieldName2": "desc"
	}
]

请参阅以下简单排序示例,假定这两个字段的缺省方向都为“升序”:

[
	"fieldNameA", "fieldNameB"
]

典型要求是使用选择器来搜索某些内容,然后按照首选方向根据指定的字段对结果进行排序。

要使用排序,必须定义包含排序字段的索引。 如果使用 json 索引,那么必须按排序顺序指定字段。

当前,IBM Cloudant 查询不支持具有不同排序顺序的多个字段,因此方向必须全部为升序或全部为降序。

如果方向为升序,那么可以使用字符串而不是对象来指定排序字段。

对于针对无法确定要排序的字段类型的 text 索引的排序查询中的字段名称,可能需要指定字段类型。 例如:

{
	"<fieldname>:string": "asc"
}
何时指定字段类型
查询使用哪个索引? 字段类型需求
JSON 索引
所有文档中所有字段的文本索引 如果数据库包含排序字段具有一种类型的文档,请在查询中指定排序字段。 另外,如果包含排序字段具有不同类型的文档,请在查询中指定排序字段。
任何其他文本索引 指定查询中所有排序字段的类型。

使用语法时,将创建所有文档中所有字段的文本索引: "index": {}.

当字段包含不同的数据类型时,未定义排序顺序。 此特征是文本和视图索引之间的重要差异。 在将来的版本中,具有不同数据类型的字段的排序行为可能会更改。

请参阅使用排序的简单查询的以下示例:

{
	"selector": {
		"Actor_name": "Robert De Niro"
	},
	"sort": [
		{
			"Actor_name": "asc"
		},
		{
			"Movie_runtime": "asc"
		}
	]
}

过滤字段

在从数据库中进行选择时,可以精确指定为文档返回的字段。 以下列表中显示了这两个优点:

  • 您的结果仅限于文档中应用程序所需的部分。
  • 减少响应大小。

要返回的字段指定为数组。

响应中仅包含指定的过滤器字段。不会自动包含 _id 或其他元数据字段。

请参阅以下从匹配文档选择性检索字段的示例:

{
	"selector": {
		"Actor_name": "Robert De Niro"
	},
	"fields": [
		"Actor_name",
		"Movie_year",
		"_id",
		"_rev"
	]
}

分页

IBM Cloudant 查询支持通过书签字段进行分页。 每个 _find 响应都包含一个书签- IBM Cloudant 用于确定在以后进行查询时从何处恢复的令牌。 要获取下一组查询结果,请将先前响应中收到的书签添加到下一个请求。 请记住保持选择器相同,否则您会收到意外的结果。 要向后分页,可以使用先前的书签来返回先前的结果集。

书签的存在并不能保证更多结果。 您可以通过将返回的结果数与请求的页面大小进行比较来测试您是否处于结果集的末尾。 如果返回的结果小于限制,那么不会在结果集中返回更多结果。

说明计划

IBM Cloudant 查询选择要用于响应查询的索引,除非在查询时指定索引。

当您指定要使用的索引时, IBM Cloudant 查询使用以下逻辑:

  • 查询规划器将查看选择器部分,并查找与查询中使用的运算符和字段最匹配的索引。 如果两个或更多 JSON 类型索引匹配,那么首选索引中字段数最小的索引。 如果仍存在两个或多个候选索引,那么将选择具有第一个字母名称的索引。
  • 如果 json 类型索引 text 类型索引可能都满足选择器,那么缺省情况下会选择 json 索引。
  • 满足以下条件时,将选择 text 类型索引:
    • json 类型索引 text 类型索引存在于同一字段中 (例如 fieldone)。
    • 只能通过使用 text 类型索引来满足选择器。

例如,假定您具有 text 类型索引和字段 foojson 类型索引,并且要使用类似于以下样本的选择器:

{
	"foo": {
		"$in": ["red","blue","green"]
	}
}

IBM Cloudant 查询使用 text 类型索引,因为 json 类型索引无法满足选择器。

但是,您可以使用具有相同索引的其他选择器:

{
	"foo": {
		"$gt": 2
	}
}

在此示例中, IBM Cloudant 查询使用 json 类型索引,因为这两种类型的索引都可以满足选择器。

要标识特定查询正在使用的索引,请将 POST 发送到数据库的 _explain 端点,并将该查询作为数据。 正在使用的索引的详细信息显示在结果中的 index 对象中。

请参阅以下使用 HTTP 的示例,以显示如何识别用于应答查询的索引:

POST /movies/_explain HTTP/1.1
Host: $SERVICE_URL
Content-Type: application/json
{
	"selector": {
		"$text": "Pacino",
		"year": 2010
	}
}

请参阅以下示例,该示例使用命令行来显示如何识别用于应答查询的索引:

curl "$SERVICE_URL/movies/_explain" \
	-X POST \
	-H "Content-Type: application/json" \
	-d '{
		"selector": {
			"$text": "Pacino",
			"year": 2010
		}
	}'
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.ExplainResult;
import com.ibm.cloud.cloudant.v1.model.PostExplainOptions;

import java.util.HashMap;
import java.util.Map;

Cloudant service = Cloudant.newInstance();

Map<String, Object> selector = new HashMap<>();
selector.put("$text", "Pacino");
selector.put("year", 2010);

PostExplainOptions explainOptions =
    new PostExplainOptions.Builder()
        .db("movies")
        .selector(selector)
        .build();

ExplainResult response =
    service.postExplain(explainOptions).execute()
        .getResult();

System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';

const service = CloudantV1.newInstance({});

let selector: CloudantV1.Selector = {
    '$text': 'Pacino',
    'year': 2010
};

service.postExplain({
  db: 'movies',
  selector: selector
}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1

service = CloudantV1.new_instance()

response = service.post_find(
  db='movies',
  selector={'$text': 'Pacino', 'year': 2010}
).get_result()

print(response)
postExplainOptions := service.NewPostExplainOptions(
    "movies",
    map[string]interface{}{
        "$text": "Pacino",
        "year":  2010,
    },
)

explainResult, _, err := service.PostExplain(postExplainOptions)
if err != nil {
  panic(err)
}

b, _ := json.MarshalIndent(explainResult, "", "  ")
fmt.Println(string(b))

先前的 Go 示例需要以下导入块:

import (
   "encoding/json"
   "fmt"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

请参阅以下示例响应,该响应显示了用于应答查询的索引:

{
	"dbname": "$ACCOUNT/movies",
	"index": {
		"ddoc": "_design/32372935e14bed00cc6db4fc9efca0f1537d34a8",
		"name": "32372935e14bed00cc6db4fc9efca0f1537d34a8",
		"type": "text",
		"def": {
			"default_analyzer": "keyword",
			"default_field": {},
			"selector": {},
			"fields": []
		}
	},
	"selector": {
		"$and": [
			{
				"$default": {
					"$text": "Pacino"
				}
			},
			{
				"year": {
					"$eq": 2010
				}
			}
		]
	},
	"opts": {
		"use_index": [],
		"bookmark": [],
		"limit": 10000000000,
		"skip": 0,
		"sort": {},
		"fields": "all_fields",
		"r": [
			49
		],
		"conflicts": false
	},
	"limit": 200,
	"skip": 0,
	"fields": "all_fields",
	"query": "(($default:Pacino) AND (year_3anumber:2010))",
	"sort": "relevance"
}

要指示查询使用特定索引,请向查询添加 use_index 参数。

use_index 参数的值采用下列其中一种格式:

  • "use_index": "$DDOC"
  • "use_index": ["$DDOC","$INDEX_NAME"]

请参阅以下示例查询,其中包含使用特定索引的指示信息:

{
	"selector": {
		"$text": "Pacino",
		"year": 2010
	},
	"use_index": "_design/32372935e14bed00cc6db4fc9efca0f1537d34a8"
}