使用IBM Cloudant搜索
搜索索引提供了一种使用 Lucene 查询解析器语法查询数据库的方法。 搜索索引使用文档中的一个或多个字段。
您可以使用搜索索引运行查询,根据文档包含的内容查找文档,或使用组、面或地理搜索。
要创建搜索索引,需要在数据库的设计文档中添加JavaScript函数。 索引会在处理完一个搜索请求或服务器检测到文档更新后建立。 index
功能接受以下参数:
- 字段名称 - 查询索引时要使用的字段名称。 如果将该参数设置为
default
,则在查询语法中没有指定字段时,将查询该字段。 - 您要索引的数据,例如
doc.address.country
。 - (Optional) The third parameter includes the following fields:
boost
,facet
,index
, andstore
. 稍后将详细介绍这些字段。
默认情况下,搜索索引响应会返回 25 条记录。 使用 limit
参数可以更改返回的行数。 不过,搜索结果集仅限于 200 行。 每个回复都包含一个 bookmark
字段。 您可以在以后的查询中包含 bookmark
字段的值,以查看响应。
您可以使用以下方法之一查询 API:URI、IBM Cloudant。Dashboard、curl 或浏览器插件(如 Postman 或 RESTClient)。
请参阅以下定义搜索索引的设计文档示例:
{
"_id": "_design/search_example",
"indexes": {
"animals": {
"index": "function(doc){ ... }"
}
}
}
搜索索引分区类型
搜索索引的分区类型继承自 options.partitioned
索引 字段。
索引功能
如果尝试使用不存在的数据字段编制索引,则会失败。 为避免这一问题,请使用适当的 保护子句。
您的索引功能在内存受限的环境中运行,而文档本身就是该环境中使用的内存的一部分。 你的代码堆栈和文档必须位于该内存内。 文件最大容量限制为 64 MB。
在搜索索引中,不要用多个数据类型对同一字段名建立索引。 如果在同一个搜索索引函数中,同一个字段名被索引为不同的数据类型,则可能会出现错误。 当您查询包含 was indexed without position data
字段的搜索索引时,会出现此错误。 例如,不要在同一个搜索索引功能中包含这两行。 这些行将 myfield
字段索引为两种不同的数据类型:字符串 "this is a string"
和数字 123
。
index("myfield", "this is a string");
index("myfield", 123);
索引字段中包含的函数是一个JavaScript函数 为数据库中的每个文档调用。 该函数以文档为参数、 从中提取一些数据、 然后调用 index
字段中定义的函数来索引这些数据。
函数 index
接受三个参数,其中第三个参数为可选参数。
第一个参数是查询索引时要使用的字段名称、 该名称在后面的查询的 Lucene 语法部分中指定。 下面的查询就是一个例子:
query=color:red
Lucene 字段名称 color
是 index
函数的第一个参数。
参数 query
可以缩写为 q
、 因此,查询的另一种写法如下例所示。
q=color:red
如果在定义名称时使用了特殊值 "default"
、 就不必在查询时指定字段名称。 其效果是可以简化查询:
query=red
第二个参数是要索引的数据。 在编制数据索引时,请牢记以下信息:
- 该数据必须是字符串、数字或布尔值。 其他类型的索引函数调用会返回错误信息。
- 如果由于这个原因或其他原因,在函数运行时返回错误,则不会将文档添加到搜索索引中。
第三个可选参数是一个JavaScript对象,包含以下字段:
选项 | 描述 | 值 | 缺省值 |
---|---|---|---|
boost |
指定搜索结果相关性的数字。 索引中提升值大于 1 的内容比没有提升值的内容更相关。 提升值小于 1 的内容并不那么相关。 | 正浮点数 | 1(无提升) |
facet |
创建分面索引。 更多信息,请参阅 切面。 | true |
false |
index |
是否为数据编制索引,如果是,如何编制。 如果设置为 false ,则数据不能用于搜索,但如果 store 设置为 true ,则仍可从索引中检索。 更多信息,请参阅 分析仪。 |
true , false |
true |
store |
如果 true ,则在搜索结果中返回该值;否则,不返回该值。 |
true , false |
false |
如果不设置 store
参数、 则不会在响应查询时返回文档的索引数据结果。
请参见以下搜索索引功能示例:
function(doc) {
index("default", doc._id);
if (doc.min_length) {
index("min_length", doc.min_length, {"store": true});
}
if (doc.diet) {
index("diet", doc.diet, {"store": true});
}
if (doc.latin_name) {
index("latin_name", doc.latin_name, {"store": true});
}
if (doc.class) {
index("class", doc.class, {"store": true});
}
}
存储与include_docs=true
当 IBM Cloudant 返回搜索数据时,您可以在以下选项中选择:store: true
或 include_docs=true
。 请参阅以下描述:
- 在索引时,选择
{store: true}
选项。 此选项表示您正在处理的字段需要存储在索引中。 即使字段本身没有用于索引,也可以对其进行“存储”。 例如,您可能想“存储”一个电话号码,即使您的搜索算法不包括按电话号码搜索。 - 查询时,请发送电子邮件至
?include_docs=true
,告知 IBM Cloud 您希望返回每个匹配文档的全文。
第一种选择意味着索引更大,但这是检索数据的最快捷方式。 第二种方案虽然索引较小,但会增加 IBM Cloud 的查询时间,因为它在计算搜索结果集后必须获取文档正文。 此过程可能会比较慢,并给 IBM Cloud 集群带来额外负担。
如果可能,请按照以下指南选择第一个选项:
- 仅对需要搜索的字段进行索引。
- 仅存储查询时需要检索的字段。
索引保护条款
index
函数要求将要索引的数据字段名作为第二个参数。 但是、 如果文档中不存在该数据字段、 就会发生错误。 解决办法是使用适当的“保护子句”检查字段是否存在。 该子句包含预期的数据类型 的预期数据类型。
请参阅下面的定义示例,该示例没有对索引数据字段的类型进行任何验证:
if (doc.min_length) {
index("min_length", doc.min_length, {"store": true});
}
您可以使用JavaScript typeof
操作符来执行保护子句测试。 如果字段存在并具有预期的类型、 将返回正确的类型名称。 保护子句测试成功,这意味着使用索引函数是安全的。 如果字段不存在、 就不会返回预期的字段类型、 这就是为什么你不会尝试索引该字段。
如果测试了以下值之一,JavaScript就会认为结果为假:
- 未定义
- Null
- 数字 +0
- 数字-0
- NaN (不是数字)
- ""(空字符串)
请参阅下面的示例,该示例使用保护子句检查所需数据字段是否存在、 并保存一个数字,然后再尝试索引:
if (typeof doc.min_length === 'number') {
index("min_length", doc.min_length, {"store": true});
}
使用通用保护子句测试,确保候选数据字段的类型已定义。
请参阅下面的“通用”保护子句示例:
if (typeof doc.min_length) !== 'undefined') {
// The field exists, and does have a type, so we can proceed to index using it.
...
}
分析仪
分析器是定义如何识别文本中术语的设置。 更多信息,请参阅 搜索分析器。
如果需要 多语言索引,分析仪会很有帮助。
下表列出了IBM Cloudant搜索支持的通用分析仪列表:
分析器 | 描述 |
---|---|
classic |
约3.1 版的标准 Lucene 分析器。 |
email |
与 standard 分析器类似,但会更努力地匹配作为完整标记的电子邮件地址。 |
keyword |
输入完全没有标记化。 |
simple |
在非字母处分割文本。 |
simple_asciifolding |
在非字母处分割文本。 将字符转换为最接近的ASCII等效字符 |
standard |
默认分析仪。 它实现了 Unicode™ 文本分割算法) 中的分词规则。 |
whitespace |
在空白边界分割文本。 |
请参阅以下分析器文档示例:
{
"_id": "_design/analyzer_example",
"indexes": {
"INDEX_NAME": {
"index": "function (doc) { ... }",
"analyzer": "$ANALYZER_NAME"
}
}
}
特定语言分析仪
这些分析器会省略特定语言中的常用词、 许多还 删除了前缀和后缀。 语言名称也是分析器的名称。
arabic
armenian
basque
bulgarian
brazilian
catalan
cjk
(Chinese, Japanese, Korean)chinese
(smartcn
)czech
danish
dutch
english
finnish
french
german
greek
galician
hindi
hungarian
indonesian
irish
italian
japanese
(kuromoji
)latvian
norwegian
persian
polish
(stempel
)portuguese
romanian
russian
spanish
swedish
thai
turkish
特定语言分析仪针对指定语言进行了优化。 不能将通用分析仪与特定语言分析仪结合使用。 相反,您可以使用 perfield
分析器 为文档中的不同字段选择不同的分析器。
每场分析仪
分析仪 perfield
可为不同领域配置多个分析仪。
请参阅下面的示例,它为不同字段定义了不同的分析器:
{
"_id": "_design/analyzer_example",
"indexes": {
"INDEX_NAME": {
"analyzer": {
"name": "perfield",
"default": "english",
"fields": {
"spanish": "spanish",
"german": "german"
}
},
"index": "function (doc) { ... }"
}
}
}
停止词语
停止词是不会被索引的词。 您可以将分析器字符串转化为对象,从而在设计文档中定义它们。
分析器 keyword
、simple
和 whitespace
不支持停顿词。
下面列出了 standard
分析器的默认停用词:
"a", "an", "and", "are", "as", "at", "be", "but", "by", "for", "if",
"in", "into", "is", "it", "no", "not", "of", "on", "or", "such",
"that", "the", "their", "then", "there", "these", "they", "this",
"to", "was", "will", "with"
请参阅下面定义非索引("停顿")词的示例:
{
"_id": "_design/stop_words_example",
"indexes": {
"INDEX_NAME": {
"analyzer": {
"name": "portuguese",
"stopwords": [
"foo",
"bar",
"baz"
]
},
"index": "function (doc) { ... }"
}
}
}
测试分析仪标记化
您可以通过向 _search_analyze
端点发布样本数据来测试分析仪标记化的结果。
请参见以下示例,该示例使用 HTTP 来测试 keyword
分析器:
Host: $ACCOUNT.cloudant.com
POST /_search_analyze HTTP/1.1
Content-Type: application/json
{"analyzer":"keyword", "text":"ablanks@renovations.com"}
请参阅下面使用命令行测试 keyword
分析仪的示例:
curl "https://$ACCOUNT.cloudant.com/_search_analyze" \
-H "Content-Type: application/json" \
-d '{"analyzer":"keyword", "text":"ablanks@renovations.com"}'
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.PostSearchAnalyzeOptions;
import com.ibm.cloud.cloudant.v1.model.SearchAnalyzeResult;
Cloudant service = Cloudant.newInstance();
PostSearchAnalyzeOptions searchAnalyzerOptions =
new PostSearchAnalyzeOptions.Builder()
.analyzer("keyword")
.text("ablanks@renovations.com")
.build();
SearchAnalyzeResult response =
service.postSearchAnalyze(searchAnalyzerOptions).execute()
.getResult();
System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';
const service = CloudantV1.newInstance({});
service.postSearchAnalyze({
analyzer: 'keyword',
text: 'ablanks@renovations.com',
}).then(response => {
console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1
service = CloudantV1.new_instance()
response = service.post_search_analyze(
analyzer='keyword',
text='ablanks@renovations.com'
).get_result()
print(response)
postSearchAnalyzeOptions := service.NewPostSearchAnalyzeOptions(
"keyword",
"ablanks@renovations.com",
)
searchAnalyzeResult, _, err := service.PostSearchAnalyze(postSearchAnalyzeOptions)
if err != nil {
panic(err)
}
b, _ := json.MarshalIndent(searchAnalyzeResult, "", " ")
fmt.Println(string(b))
前面的围棋示例需要以下导入块:
import (
"encoding/json"
"fmt"
"github.com/IBM/cloudant-go-sdk/cloudantv1"
)
请看下面测试 keyword
分析器的结果:
{
"tokens": [
"ablanks@renovations.com"
]
}
请参见以下示例,该示例使用 HTTP 来测试 standard
分析器:
Host: $ACCOUNT.cloudant.com
POST /_search_analyze HTTP/1.1
Content-Type: application/json
{"analyzer":"standard", "text":"ablanks@renovations.com"}
请参阅下面使用命令行测试 standard
分析仪的示例:
curl "https://$ACCOUNT.cloudant.com/_search_analyze" -H "Content-Type: application/json"
-d '{"analyzer":"standard", "text":"ablanks@renovations.com"}'
请看下面的 standard
分析仪测试结果:
{
"tokens": [
"ablanks",
"renovations.com"
]
}
查询
创建搜索索引后,就可以对其进行查询。
-
使用以下请求运行分区查询:
GET /$DATABASE/_partition/$PARTITION_KEY/_design/$DDOC/_search/$INDEX_NAME
-
使用以下请求运行全局查询:
GET /$DATABASE/_design/$DDOC/_search/$INDEX_NAME
使用 query
参数指定搜索。
请参见以下示例,该示例使用 HTTP 查询分区索引:
GET /$DATABASE/_partition/$PARTITION_KEY/_design/$DDOC/_search/$INDEX_NAME?include_docs=true&query="*:*"&limit=1 HTTP/1.1
Content-Type: application/json
Host: $ACCOUNT.cloudant.com
请参阅下面使用命令行查询分区索引的示例:
curl "https://$ACCOUNT.cloudant.com/$DATABASE/_partition/$PARTITION_KEY/_design/$DDOC/_search/$INDEX_NAME?include_docs=true&query=\"*:*\"&limit=1"
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.PostPartitionSearchOptions;
import com.ibm.cloud.cloudant.v1.model.SearchResult;
Cloudant service = Cloudant.newInstance();
PostPartitionSearchOptions searchOptions =
new PostPartitionSearchOptions.Builder()
.db("<db-name>")
.partitionKey("<partition-key>")
.ddoc("<ddoc>")
.index("<index-name>")
.query("*:*")
.includeDocs(true)
.limit(1)
.build();
SearchResult response =
service.postPartitionSearch(searchOptions).execute()
.getResult();
System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';
const service = CloudantV1.newInstance({});
service.postSearch({
db: '<db-name>',
partitionKey: '<partition-key>',
ddoc: '<ddoc>',
index: '<index-name>',
query: '*:*',
includeDocs: true,
limit: 1
}).then(response => {
console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1
service = CloudantV1.new_instance()
response = service.post_search(
db='<db-name>',
partition_key='<partition-key>',
ddoc='<ddoc>',
index='<index-name>',
query='*:*',
include_docs=True,
limit=1
).get_result()
print(response)
postPartitionSearchOptions := service.NewPostPartitionSearchOptions(
"<db-name>",
"<partition-key>",
"<ddoc>",
"<index-name>",
"*:*",
)
postPartitionSearchOptions.SetIncludeDocs(true)
postPartitionSearchOptions.SetLimit(1)
searchResult, _, err := service.PostPartitionSearch(postPartitionSearchOptions)
if err != nil {
panic(err)
}
b, _ := json.MarshalIndent(searchResult, "", " ")
fmt.Println(string(b))
前面的围棋示例需要以下导入块:
import (
"encoding/json"
"fmt"
"github.com/IBM/cloudant-go-sdk/cloudantv1"
)
请参见以下示例,该示例使用 HTTP 查询全局索引:
GET /$DATABASE/_design/$DDOC/_search/$INDEX_NAME?include_docs=true&query="*:*"&limit=1 HTTP/1.1
Content-Type: application/json
Host: $ACCOUNT.cloudant.com
请参阅下面使用命令行查询全局索引的示例:
curl "https://$ACCOUNT.cloudant.com/$DATABASE/_design/$DDOC/_search/$INDEX_NAME?include_docs=true&query=\"*:*\"&limit=1"
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.PostSearchOptions;
import com.ibm.cloud.cloudant.v1.model.SearchResult;
Cloudant service = Cloudant.newInstance();
PostSearchOptions searchOptions = new PostSearchOptions.Builder()
.db("<db-name>")
.ddoc("<ddoc>")
.index("<index-name>")
.query("*:*")
.includeDocs(true)
.limit(1)
.build();
SearchResult response =
service.postSearch(searchOptions).execute()
.getResult();
System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';
const service = CloudantV1.newInstance({});
service.postSearch({
db: '<db-name>',
ddoc: '<ddoc>',
index: '<index-name>',
query: '*:*',
includeDocs: true,
limit: 1
}).then(response => {
console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1
service = CloudantV1.new_instance()
response = service.post_search(
db='<db-name>',
ddoc='<ddoc>',
index='<index-name>',
query='*:*',
include_docs=True,
limit=1
).get_result()
print(response)
postSearchOptions := service.NewPostSearchOptions(
"<db-name>",
"<ddoc>",
"<index-name>",
"*:*",
)
postSearchOptions.SetIncludeDocs(true)
postSearchOptions.SetLimit(1)
searchResult, _, err := service.PostSearch(postSearchOptions)
if err != nil {
panic(err)
}
b, _ := json.MarshalIndent(searchResult, "", " ")
fmt.Println(string(b))
前面的围棋示例需要以下导入块:
import (
"encoding/json"
"fmt"
"github.com/IBM/cloudant-go-sdk/cloudantv1"
)
查询参数
You must enable 刻面 before you can use the following parameters: counts
and drilldown
.
自变量 | 描述 | 可选 | Type | 支持的值 | 分区查询 |
---|---|---|---|---|---|
bookmark |
从上次搜索中获得的书签。 使用该参数可对结果进行分页。 如果书签后没有结果,则会得到一个空行数组和相同书签的响应,确认结果列表结束。 | yes |
字符串 | 是 | |
counts |
该字段定义了一个字符串字段名数组,要求对其进行计数。 响应包括与搜索查询匹配的文档中该字段名的每个唯一值的计数。 必须启用 切面 功能才能使用该参数。 | 是 | JSON | 字段名的 JSON 数组。 | 否 |
drilldown |
该字段可以多次使用。 每个用途都定义了一对字段名和一个值。 搜索只匹配包含指定字段所提供值的文档。 It differs from using "fieldname:value" in the q parameter only in that the values aren't analyzed. 必须启用 切面 功能才能使用该参数。 |
否 | JSON | 一个 JSON 数组,包含两个元素:字段名称和值。 | 是 |
group_field |
对搜索匹配结果进行分组的字段。 | 是 | 字符串 | 包含字符串字段名称的字符串。 不能使用包含其他数据(如数字、对象或数组)的字段。 | 否 |
group_limit |
最大组数。 只有指定 group_field 时才能使用该字段。 |
是 | 数值 | 否 | |
group_sort |
该字段在使用 group_field 的搜索中定义组的顺序。 默认排序顺序为相关性。 |
是 | JSON | 该字段可以具有与排序字段相同的值,因此支持单字段和字段数组。 | 否 |
highlight_fields |
指定要高亮显示的字段。 如果指定,结果对象将包含一个 highlights 字段,每个指定字段都有一个条目。 |
是 | 字符串数组 | 是 | |
highlight_pre_tag |
在高亮输出中高亮字之前插入的字符串。 | 是,默认为 <em> |
字符串 | 是 | |
highlight_post_tag |
在高亮输出中高亮字后插入的字符串。 | 是,默认为 </em> |
字符串 | 是 | |
highlight_number |
高亮返回的片段数量。 如果搜索词超过片段大小,则返回整个搜索词。 | 是,默认为 1 | 数值 | 是 | |
highlight_size |
将字段内容分割成若干个字符,即所谓的片段,并只高亮显示指定片段内的匹配内容。 | 是,默认为 100 个字符 | 数值 | 是 | |
include_docs |
在答复中包括文件的全部内容。 | 是 | 布尔值 | 是 | |
include_fields |
要包含在搜索结果中的字段名的 JSON 数组。 任何包含的字段都必须使用 store:true 选项进行索引。 |
是的,默认为所有字段。 | 字符串数组 | 是 | |
limit |
将返回的文件数量限制为指定数量。 对于分组搜索,该参数限制了每个组的文件数量。 | 是 | 数值 | 限值可以是 200(含 200)以下的任何正整数。 | 是 |
q |
query 的缩写。 运行 Lucene 查询。 |
否 | 字符串或数字 | 是 | |
query |
运行 Lucene 查询。 | 否 | 字符串或数字 | 是 | |
ranges |
此字段定义了分面数字搜索字段的范围。 值是一个 JSON 对象,其中字段名称是分面数字搜索字段,字段值是 JSON 对象。 JSON 对象的字段名称是范围的名称。 值是描述范围的字符串,例如 "[0 TO 10]" 。 |
是 | JSON | 值必须是一个对象,其字段的值必须是对象。 这些对象的字段值必须是有范围的字符串。 | 否 |
sort |
指定结果的排序顺序。 在分组搜索中(使用 group_field 时),该参数指定组内的排序顺序。 默认排序顺序为相关性。 |
是 | JSON | 形式为 "fieldname<type>" 或 -fieldname<type> 的 JSON 字符串,表示降序排列。 其中 fieldname 是字符串或数字字段的名称,type 是数字、字符串或由字符串组成的 JSON 数组。 type 部分是可选的,默认为 number 。
Some examples are "foo" , "-foo" , "bar<string>" , "-foo<number>" , and ["-foo<number>","bar<string>"] .
用于排序的字符串字段不能是分析字段。 用于排序的字段必须由用于搜索查询的同一索引器编制索引。 |
是 |
stale |
不要等索引建立完成后再返回结果。 | 是 | 字符串 | OK | 是 |
不要同时使用 bookmark
和 stale
选项。 这些选项限制了用于响应的分片副本的选择。 这些选项一起使用时,在尝试联系速度较慢或不可用的副本时可能会造成问题。
使用 include_docs=true
可能会 影响性能。
相关性
当可能返回多个结果时、 可以对它们进行排序。 默认情况下 排序顺序由“相关性”决定。
相关性是根据
ApacheLucene 评分。 举个例子、 如果在一个简单的数据库中搜索 "example
"一词、 可能会有两份文档包含该词。 如果一份文件提到 example
这个词 10 次、 而第二份文档只提到两次、
那么第一份文档被认为更“相关”。
如果不提供 sort
参数、 则默认使用相关性。 得分最高的比赛首先返回。
如果提供 sort
参数、 则会按该顺序返回匹配结果、 忽略相关性。
如果您想使用 sort
参数、 并在搜索结果中按相关性排序、 在 sort
参数中使用特殊字段 -<score>
或 <score>
。
发布搜索查询
除了使用 GET
HTTP 方法,您还可以使用 POST
。
POST
查询的主要优点是可以有一个请求体、 因此您可以将请求指定为 JSON 对象。 上表中的每个参数都与请求正文中 JSON 对象的一个字段相对应。
请参见以下示例,该示例使用 HTTP 向 POST
发送搜索请求:
POST /db/_design/ddoc/_search/searchname HTTP/1.1
Content-Type: application/json
Host: $ACCOUNT.cloudant.com
请参阅下面使用命令行 POST
搜索请求的示例:
curl "https://$ACCOUNT.cloudant.com/$DATABASE/_design/$DDOC/_search/$INDEX_NAME" -X POST -H "Content-Type: application/json" -d @search.json
请参阅以下包含搜索请求的 JSON 文档示例:
{
"q": "index:my query",
"sort": "foo",
"limit": 3
}
查询语法
IBM Cloudant搜索查询语法基于
Lucene 语法。 搜索查询采用 name:value
的形式,除非省略了名称、 在这种情况下,它们使用默认字段、 如以下示例所示:
请参阅以下搜索查询表达式示例:
// Birds
class:bird
// Animals that begin with the letter "l"
l*
// Carnivorous birds
class:bird AND diet:carnivore
// Herbivores that start with letter "l"
l* AND diet:herbivore
// Medium-sized herbivores
min_length:[1 TO 3] AND diet:herbivore
// Herbivores that are 2m long or less
diet:herbivore AND min_length:[-Infinity TO 2]
// Mammals that are at least 1.5m long
class:mammal AND min_length:[1.5 TO Infinity]
// Find "Meles meles"
latin_name:"Meles meles"
// Mammals who are herbivore or carnivore
diet:(herbivore OR omnivore) AND class:mammal
// Return all results
*:*
对多个字段的查询可进行逻辑组合、 组和字段可进一步分组。 可用的逻辑运算符区分大小写,它们是 AND
、
+
,
OR
,
NOT
, and -
. 范围查询可在字符串或数字上运行。
如果需要模糊搜索、 可以运行带 ~
的查询,查找与搜索词类似的词。 例如
look~
finds the terms book
and took
.
如果范围查询的上界都是只包含数字的字符串,则上界将被视为数字而不是字符串。 例如,如果使用查询 mod_date:["20170101" TO "20171231"]
进行搜索,结果将包括 mod_date
位于数值 20170101 和 20171231 之间的文档,而不是位于字符串 "20170101 "和 "20171231 "之间的文档。
您可以通过添加 ^
和正数来改变搜索词的重要性。 这种改变会使包含该术语的匹配结果更加相关或不太相关、 与提升值的幂成正比。 默认值为 1、 表示不增加或减少匹配强度。 0 - 1 的十进制值会降低重要性、 使匹配强度变弱。 大于 1 的值会增加重要性、 使匹配强度更强。
支持通配符搜索、 用于单 ?
) 和多 *
) 字符搜索。 例如
dat?
would match date
and data
, and dat*
would match date
,
data
,
database
, and dates
. 通配符必须位于搜索词之后。
使用 *:*
返回所有结果。
搜索结果集限制为 200 行、 默认情况下返回 25 行。 可以使用 * 来更改返回的行数。 通过使用 limit
parameter.
如果搜索查询未指定 "group_field"
参数、 响应就会包含一个书签。 如果以后将此书签作为 URL 参数提供,则响应将跳过已查看的行,从而快速轻松地获取下一组结果。
如果在搜索查询中包含 "group_field"
参数,则响应永远不会包含书签。
group_field
、group_limit
和 group_sort
选项只有在进行全局查询时可用。
如果要对以下字符进行搜索,则需要将其转义:
+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /
要转义这些字符中的一个、 使用前面的反斜杠字符 \
)。
搜索查询的响应包括每个结果的 order
字段。 The order
field is an array where the first element is the field or fields that are specified in the sort
parameter. 如果查询中未包含 sort
参数、
则 order
字段包含 Lucene 相关性得分。 如果使用 地理搜索 中描述的 sort by distance
功能、 那么第一个元素就是与某点的距离。
距离用公里或英里来测量。
顺序数组中的第二个元素可以忽略。 仅用于故障排除。
刻面
IBM Cloudant搜索还支持分面搜索,从而 可快速、轻松地发现匹配的综合信息。 您可以使用特殊的 ?q=*:*
查询语法匹配所有文档、 并使用返回的面来完善查询。 要指明某个字段必须为分面查询编制索引、 在选项中设置 {"facet": true}
。
请参阅下面的搜索查询示例,指定启用分面搜索:
function(doc) {
index("type", doc.type, {"facet": true});
index("price", doc.price, {"facet": true});
}
要使用分面 索引中的所有文档都必须包含已启用分面的所有字段。 如果您的文件不包括所有字段、 您将收到一个 bad_request
错误,理由如下:“该 field_name
不存在”。 如果每个文档不包含面的所有字段、 为每个字段创建单独的索引。 如果不为每个字段创建单独的索引、 则必须只包含包含所有字段的文档。 使用单一 if
语句验证每个文档中是否存在字段。
请参阅下面的 if
语句示例,以验证每个文档中是否存在必填字段:
if (typeof doc.town == "string" && typeof doc.name == "string") {
index("town", doc.town, {facet: true});
index("name", doc.name, {facet: true});
}
计数
counts
选项只有在进行全局查询时可用。
counts
面语法使用一个字段列表、 并返回每个指定字段的每个唯一值的查询结果数。
count
操作只有在索引值为字符串时才有效。 索引值不能是混合类型。 例如 如果索引了 100 个字符串 和一个数字、 那么索引就不能用于 count
操作。 您可以使用 typeof
操作符检查类型、 运算符检查类型,并使用 parseInt
进行转换、
parseFloat
, or .toString()
functions.
请参阅以下使用 counts
面语法的查询示例:
?q=*:*&counts=["type"]
请参阅使用 counts
面语法后的响应示例:
{
"total_rows":100000,
"bookmark":"g...",
"rows":[...],
"counts":{
"type":{
"sofa": 10,
"chair": 100,
"lamp": 97
}
}
}
drilldown
drilldown
选项只有在进行全局查询时可用。
您可以将结果限制为维度等于指定标签的文档。 通过在搜索查询中添加 drilldown=["dimension","label"]
来限制搜索结果。 您可以包含多个 drilldown
参数来限制多个维度的结果。
使用 drilldown
参数类似于在 q
参数中使用 key:value
、 但 drilldown
参数会返回分析器可能跳过的值。
例如 如果分析器没有索引像 "a"
、 当您指定 drilldown=["key","a"]
时,drilldown
参数就会返回它。
范围
ranges
选项只有在进行全局查询时可用。
range
面语法重新使用了范围的标准 Lucene 语法 返回符合每个指定类别的结果计数。 包含范围查询用括号 [
,]
) 表示。 排他性范围查询用大括号 {
,}
) 表示。
索引值不能是混合类型。 例如 如果索引了 100 个字符串 和一个数字、 那么索引就不能用于 range
操作。 您可以使用 typeof
操作符检查类型、 运算符检查类型,并使用 parseInt
进行转换、
parseFloat
, or .toString()
functions.
请参阅以下使用分面搜索匹配 ranges
的请求示例:
?q=*:*&ranges={"price":{"cheap":"[0 TO 100]","expensive":"{100 TO Infinity}"}}
请参阅下面的示例,了解在分面搜索中进行 ranges
检查后的结果:
{
"total_rows":100000,
"bookmark":"g...",
"rows":[...],
"ranges": {
"price": {
"expensive": 278682,
"cheap": 257023
}
}
}
地域搜索
除了根据文本字段的内容进行搜索外,您还可以根据结果与地理坐标的距离进行排序、 您还可以根据与地理坐标的距离对结果进行排序。
要以这种方式对结果进行排序、 您必须为两个数字字段 表示经度和纬度。
然后,您可以使用特殊的 <distance...>
排序字段进行查询、 该字段需要五个参数:
- Longitude field name - The name of your longitude field (
mylon
in the example). - Latitude field name - The name of your latitude field (
mylat
in the example). - 原点经度 - 要按距离排序的地点的经度。
- 原点纬度 - 您要按距离排序的地点的纬度。
- 单位 - 使用的单位包括:
km
表示公里,mi
表示英里。 距离会在订单字段中返回。
您可以将按距离排序与任何其他搜索查询结合起来、 如经纬度范围搜索、 或涉及非地理信息的查询。
这样 您可以在边界框内进行搜索、 并通过额外的条件缩小搜索范围。
请参见以下地理数据示例:
{
"name":"Aberdeen, Scotland",
"lat":57.15,
"lon":-2.15,
"type":"city"
}
请参阅以下包含地理数据搜索索引的设计文档示例:
function(doc) {
if (doc.type && doc.type == 'city') {
index('city', doc.name, {'store': true});
index('lat', doc.lat, {'store': true});
index('lon', doc.lon, {'store': true});
}
}
请看下面的示例,其中使用 HTTP 查询北半球城市与纽约的距离:
GET /examples/_design/cities-designdoc/_search/cities?q=lat:[0+TO+90]&sort="<distance,lon,lat,-74.0059,40.7127,km>" HTTP/1.1
Host: $ACCOUNT.cloudant.com
请参阅下面的示例,该示例使用命令行进行查询,按北半球城市到纽约的距离排序:
curl "https://$ACCOUNT.cloudant.com/examples/_design/cities-designdoc/_search/cities?q=lat:\[0+TO+90\]&sort=\"<distance,lon,lat,-74.0059,40.7127,km>\""
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.PostSearchOptions;
import com.ibm.cloud.cloudant.v1.model.SearchResult;
import java.util.Arrays;
Cloudant service = Cloudant.newInstance();
PostSearchOptions searchOptions = new PostSearchOptions.Builder()
.db("examples")
.ddoc("cities-designdoc")
.index("cities")
.query("lat:\\[0+TO+90\\]")
.sort(Arrays.asList("<distance,lon,lat,-74.0059,40.7127,km>"))
.build();
SearchResult response =
service.postSearch(searchOptions).execute()
.getResult();
System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';
const service = CloudantV1.newInstance({});
service.postSearch({
db: 'examples',
ddoc: 'cities-designdoc',
index: 'cities',
query: 'lat:\\[0+TO+90\\]',
sort: ['<distance,lon,lat,-74.0059,40.7127,km>']
}).then(response => {
console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1
service = CloudantV1.new_instance()
response = service.post_search(
db='examples',
ddoc='cities-designdoc',
index='cities',
query='lat:\\[0+TO+90\\]',
sort=['<distance,lon,lat,-74.0059,40.7127,km>']
).get_result()
print(response)
postSearchOptions := service.NewPostSearchOptions(
"examples",
"cities-designdoc",
"cities",
"lat:\\[0+TO+90\\]",
)
postSearchOptions.SetSort([]string{"<distance,lon,lat,-74.0059,40.7127,km>"})
searchResult, _, err := service.PostSearch(postSearchOptions)
if err != nil {
panic(err)
}
b, _ := json.MarshalIndent(searchResult, "", " ")
fmt.Println(string(b))
前面的围棋示例需要以下导入块:
import (
"encoding/json"
"fmt"
"github.com/IBM/cloudant-go-sdk/cloudantv1"
)
请参阅以下回复示例(缩写),其中包括按与纽约的距离排序的北半球城市列表:
{
"total_rows": 205,
"bookmark": "g1A...XIU",
"rows": [
{
"id": "city180",
"order": [
8.530665755719783,
18
],
"fields": {
"city": "New York, N.Y.",
"lat": 40.78333333333333,
"lon": -73.96666666666667
}
},
{
"id": "city177",
"order": [
13.756343205985946,
17
],
"fields": {
"city": "Newark, N.J.",
"lat": 40.733333333333334,
"lon": -74.16666666666667
}
},
{
"id": "city178",
"order": [
113.53603438866077,
26
],
"fields": {
"city": "New Haven, Conn.",
"lat": 41.31666666666667,
"lon": -72.91666666666667
}
}
]
}
突出显示搜索词
有时,获取搜索词被提及的上下文非常有用 以便向用户显示更有针对性的结果。
要获得更多强调的结果,请 在搜索查询中添加 highlight_fields
参数。 指定需要摘录的字段名、 并返回突出显示的搜索词。
默认情况下 搜索词会被置于 <em>
标记中以突出显示、 但可以使用 highlights_pre_tag
和 highlights_post_tag
参数覆盖高亮显示。
片段长度默认为 100 个字符。 可以使用 highlights_size
参数要求不同的长度。
参数 highlights_number
控制返回的片段数量、 默认为 1。
在回复中 添加了一个 highlights
字段、 每个字段名有一个子字段。
对于每个字段、 都会收到一个带搜索词的片段数组。
要使高亮显示有效 使用 store: true
选项将字段存储在索引中。
请参见以下示例,该示例使用 HTTP 进行搜索,并启用了高亮显示功能:
GET /movies/_design/searches/_search/movies?q=movie_name:Azazel&highlight_fields=["movie_name"]&highlight_pre_tag=" "&highlight_post_tag=" "&highlights_size=30&highlights_number=2 HTTP/1.1
HOST: $ACCOUNT.cloudant.com
Authorization: ...
请参阅以下示例,了解启用高亮显示后的搜索命令行:
curl "https://$ACCOUNT.cloudant.com/movies/_design/searches/_search/movies?q=\"movie_name:Azazel\"&highlight_fields=\[\"movie_name\"\]&highlight_pre_tag=\" \"&highlight_post_tag=\" \"&highlights_size=30&highlights_number=2" \
-X GET
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.PostSearchOptions;
import com.ibm.cloud.cloudant.v1.model.SearchResult;
import java.util.Arrays;
Cloudant service = Cloudant.newInstance();
PostSearchOptions searchOptions = new PostSearchOptions.Builder()
.db("movies")
.ddoc("searches")
.index("movies")
.query("movie_name:Azazel")
.highlightFields(Arrays.asList("[\"movie_name\"]"))
.highlightPreTag("\" \"")
.highlightPostTag("\" \"")
.highlightSize(30)
.highlightNumber(2)
.build();
SearchResult response =
service.postSearch(searchOptions).execute()
.getResult();
System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';
const service = CloudantV1.newInstance({});
service.postSearch({
db: 'movies',
ddoc: 'searches',
index: 'movies',
query: 'movie_name:Azazel',
highlightFields: ['["movie_name"]'],
highlightPreTag: '" "',
highlightPostTag: '" "',
highlightSize: 30,
highlightNumber: 2
}).then(response => {
console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1
service = CloudantV1.new_instance()
response = service.post_search(
db='movies',
ddoc='searches',
index='movies',
query='movie_name:Azazel',
highlight_fields=['["movie_name"]'],
highlight_pre_tag='" "',
highlight_post_tag='" "',
highlight_size=30,
highlight_number=2
).get_result()
print(response)
postSearchOptions := service.NewPostSearchOptions(
"movies",
"searches",
"movies",
"movie_name:Azazel",
)
postSearchOptions.SetHighlightFields([]string{"[\"movie_name\"]"})
postSearchOptions.SetHighlightPreTag("\" \"")
postSearchOptions.SetHighlightPostTag("\" \"")
postSearchOptions.SetHighlightSize(30)
postSearchOptions.SetHighlightNumber(2)
searchResult, _, err := service.PostSearch(postSearchOptions)
if err != nil {
panic(err)
}
b, _ := json.MarshalIndent(searchResult, "", " ")
fmt.Println(string(b))
前面的围棋示例需要以下导入块:
import (
"encoding/json"
"fmt"
"github.com/IBM/cloudant-go-sdk/cloudantv1"
)
请参阅以下高亮显示搜索结果的示例:
{
"highlights": {
"movie_name": [
" on the Azazel Orient Express",
" Azazel manuals, you"
]
}
}
搜索索引元数据
要检索有关搜索索引的信息、 向 GET
端点发送 _search_info
请求、 如下例所示。
DDOC
refers to the design document that includes the index, and INDEX_NAME
is the name of the index.
请参见以下示例,该示例使用 HTTP 请求搜索索引元数据:
GET /$DATABASE/_design/$DDOC/_search_info/$INDEX_NAME HTTP/1.1
请参阅下面使用命令行请求搜索索引元数据的示例:
curl "https://$ACCOUNT.cloudant.com/$DATABASE/_design/$DDOC/_search_info/$INDEX_NAME" \
-X GET
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.GetSearchInfoOptions;
import com.ibm.cloud.cloudant.v1.model.SearchInfoResult;
Cloudant service = Cloudant.newInstance();
GetSearchInfoOptions infoOptions =
new GetSearchInfoOptions.Builder()
.db("<db-name>")
.ddoc("<ddoc>")
.index("<index-name>")
.build();
SearchInfoResult response =
service.getSearchInfo(infoOptions).execute()
.getResult();
System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';
const service = CloudantV1.newInstance({});
service.getSearchInfo({
db: '<db-name>',
ddoc: '<ddoc>',
index: '<index-name>'
}).then(response => {
console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1
service = CloudantV1.new_instance()
response = service.get_search_info(
db='<db-name>',
ddoc='<ddoc>',
index='<index-name>'
).get_result()
print(response)
getSearchInfoOptions := service.NewGetSearchInfoOptions(
"<db-name>",
"<ddoc>",
"<index-name>",
)
searchInfoResult, _, err := service.GetSearchInfo(getSearchInfoOptions)
if err != nil {
panic(err)
}
b, _ := json.MarshalIndent(searchInfoResult, "", " ")
fmt.Println(string(b))
前面的围棋示例需要以下导入块:
import (
"encoding/json"
"fmt"
"github.com/IBM/cloudant-go-sdk/cloudantv1"
)
响应包括有关索引的信息、 的信息,如索引中的文件数量和索引在磁盘上的大小。
请参阅以下请求搜索索引元数据后的响应示例:
{
"name": "_design/DDOC/INDEX",
"search_index": {
"pending_seq": 7125496,
"doc_del_count": 129180,
"doc_count": 1066173,
"disk_size": 728305827,
"committed_seq": 7125496
}
}