全文搜索服务提供以下 REST API 接口:
在调用全文搜索的 REST API 接口前,需要首先为相应的 Class 启用搜索。 另外也请参考《存储 REST API 使用指南》中关于 API Base URL、请求格式、响应格式的说明,以及《全文搜索开发指南》的《自定义分词》章节。
GET /1.1/search/select REST API 接口提供全文搜索功能。
GET /1.1/search/select
curl -X GET \ -H "X-LC-Id: {{appid}}" \ -H "X-LC-Key: {{appkey}}" \ "https://API_BASE_URL/1.1/search/select?q=dennis&limit=200&clazz=GameScore&order=-score"
返回类似:
{ "hits": 1, "results": [ { "_app_url": "http://stg.pass.com//1/go/com.leancloud/classes/GameScore/51e3a334e4b0b3eb44adbe1a", "_deeplink": "com.leancloud.appSearchTest://leancloud/classes/GameScore/51e3a334e4b0b3eb44adbe1a", "_highlight": null, "updatedAt": "2011-08-20T02:06:57.931Z", "playerName": "Sean Plott", "objectId": "51e3a334e4b0b3eb44adbe1a", "createdAt": "2011-08-20T02:06:57.931Z", "cheatMode": false, "score": 1337 } ], "sid": "cXVlcnlUaGVuRmV0Y2g7Mzs0NDpWX0NFUmFjY1JtMnpaRDFrNUlBcTNnOzQzOlZfQ0VSYWNjUm0yelpEMWs1SUFxM2c7NDU6Vl9DRVJhY2NSbTJ6WkQxazVJQXEzZzswOw==" }
查询的参数支持:
q
skip
limit
sid
fields
highlights
*
clazz
include
user,comment
order
-score,createdAt
sort
返回结果属性介绍:
results
hits
返回结果 results 列表里是一个一个的对象,字段是你在全文搜索设置里启用的字段列表,并且有三个特殊字段:
_app_url
_deeplink
_highlight
em
最外层的 sid 用来标记本次查询结果,下次查询继续传入这个 sid 将翻页查找后 200 条数据:
curl -X GET \ -H "X-LC-Id: {{appid}}" \ -H "X-LC-Key: {{appkey}}" \ "https://API_BASE_URL/1.1/search/select?q=dennis&limit=200&clazz=GameScore&order=-score&sid=cXVlcnlUaGVuRmV0Y2g7Mzs0NDpWX0NFUmFjY1JtMnpaRDFrNUlBcTNnOzQzOlZfQ0VSYWNjUm0yelpEMWs1SUFxM2c7NDU6Vl9DRVJhY2NSbTJ6WkQxazVJQXEzZzswOw"
直到返回结果为空。
q 参数遵循 elasticsearch 的 query string 语法。建议详细阅读这个文档。这里简单做个举例说明。
如果你非常熟悉 elasticsearch 的 query string 语法,那么可以跳至地理位置信息查询一节(地理位置查询是我们在 elasticsearch 上添加的扩展功能)。
查询的关键字保留字符包括: + - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /,当出现这些字符的时候,请对这些保留字符做 URL Escape 转义。
+ - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
可乐
可口 可乐
"lady gaga"
lady gaga
nickename:逃跑计划
nickename:"lady gaga"
nickname:(逃跑计划 OR 夜空中最亮的星)
book.name:clojure OR book.content:clojure
book.*:clojure
_missing_:title
_exists_:title
上面举例根据字段查询,前提是这些字段在 class 的全文搜索设置里启用了索引。
qu?ck bro* 就是一个通配符查询,? 表示一个单个字符,而 * 表示 0 个或者多个字符。
qu?ck bro*
?
通配符其实是正则的简化,可以使用正则查询:
name:/joh?n(ath[oa]n)/
正则的语法参考 正则语法。
根据文本距离相似度(Fuzziness)来查询。例如 quikc~,默认根据 Damerau-Levenshtein 文本距离算法来查找最多两次变换的匹配项。
quikc~
例如这个查询可以匹配 quick、qukic、qukci 等。
quick
qukic
qukci
// 数字 1 到 5: count:[1 TO 5] // 2012年内 date:[2012-01-01 TO 2012-12-31] //2012 年之前 {* TO 2012-01-01}
[] 表示闭区间,{} 表示开区间。
[]
{}
还可以采用比较运算符:
age:>10 age:>=10 age:<10 age:<=10
查询可以使用括号分组:
(quick OR brown) AND fox
objectId: 558e20cbe4b060308e3eb36c
createdAt:["2015-07-30T00:00:00.000Z" TO "2015-08-15T00:00:00.000Z"]
updatedAt: [2012-01-01 TO 2012-12-31]
.iso
birthday.iso: [2012-01-01 TO 2012-12-31]
字段名.objectId
player.objectId: 558e20cbe4b060308e3eb36c and player.className: Player
avartar.url: "https://leancloud.cn/docs/app_search_guide.html#搜索_API"
假设你要排序的字段是一个数组,比如分数数组 scores,你想根据平均分来倒序排序,并且没有分数的排最后,那么可以传入:
scores
--data-urlencode 'sort=[{"scores":{"order":"desc","mode":"avg","missing":"_last"}}]'
也就是 sort 可以是一个 JSON 数组,其中每个数组元素是一个 JSON 对象:
{"scores":{"order":"desc","mode":"avg","missing":"_last"}}
排序的字段作为 key,字段可以设定下列选项:
asc
desc
mode
min
max
sum
avg
missing
_last
_first
多个字段排序就类似:
[ { "scores":{"order":"desc","mode":"avg","missing":"_last"} }, { "updatedAt": {"order":"asc"} } ]
如果 class 里某个列是 GeoPoint 类型,那么可以根据这个字段的地理位置远近来排序,例如假设字段 location 保存的是 GeoPoint类型,那么查询 [39.9, 116.4] 附近的玩家可以通过设定 sort 为:
GeoPoint
location
[39.9, 116.4]
{ "_geo_distance" : { "location" : [39.9, 116.4], "order" : "asc", "unit" : "km", "mode" : "min", } }
order 和 mode 含义跟上述复杂排序里的一致,unit 用来指定距离单位,例如 km 表示千米,m 表示米,cm 表示厘米等。
unit
km
m
cm
除了 /1.1/search/select 之外,我们还提供了 /1.1/search/mlt API 接口,用于相似文档的查询,可以用来实现相关性推荐。
/1.1/search/select
/1.1/search/mlt
假设我们有一个 Class 叫 Post 是用来保存博客文章的,我们想基于它的标签字段 tags 做相关性推荐:
Post
tags
curl -X GET \ -H "X-LC-Id: {{appid}}" \ -H "X-LC-Key: {{appkey}}" \ "https://API_BASE_URL/1.1/search/mlt?like=clojure&clazz=Post&fields=tags"
我们设定了 like 参数为 clojure,查询的相关性匹配字段 fields 是 tags,也就是从 Post 里查找 tags 字段跟 clojure 这个文本相似的对象,返回类似:
like
clojure
{ "results": [ { "tags":[ "clojure", "数据结构与算法" ], "updatedAt":"2016-07-07T08:54:50.268Z", "_deeplink":"cn.leancloud.qfo17qmvr8w2y6g5gtk5zitcqg7fyv4l612qiqxv8uqyo61n:\/\/leancloud\/classes\/Article\/577e18b50a2b580057469a5e", "_app_url":"https:\/\/leancloud.cn\/1\/go\/cn.leancloud.qfo17qmvr8w2y6g5gtk5zitcqg7fyv4l612qiqxv8uqyo61n\/classes\/Article\/577e18b50a2b580057469a5e", "objectId":"577e18b50a2b580057469a5e", "_highlight":null, "createdAt":"2016-07-07T08:54:13.250Z", "className":"Article", "title":"clojure persistent vector" }, // …… ], "sid": null }
除了可以通过指定 like 这样的相关性文本来指定查询相似的文档之外,还可以通过 likeObjectIds 指定一个对象的 objectId 列表,来查询相似的对象:
curl -X GET \ -H "X-LC-Id: {{appid}}" \ -H "X-LC-Key: {{appkey}}" \ "https://API_BASE_URL/1.1/search/mlt?likeObjectIds=577e18b50a2b580057469a5e&clazz=Post&fields=tags"
这次我们换成了查找和 577e18b50a2b580057469a5e 这个 objectId 指代的对象相似的对象。
577e18b50a2b580057469a5e
更详细的查询参数说明:
likeObjectIds
min_term_freq
min_doc_freq
max_doc_freq
_all
更多内容参考 ElasticSearch 文档。
全文搜索会对 String 类型的字段自动进行分词处理。 如果发现搜索结果不符合预期,推荐先通过 analyze API 检查分词结果(要求使用 master key)。 analyze API 也用于验证自定义词库是否生效。
analyze
curl -X GET \ -H "X-LC-Id: {{appid}}" \ -H "X-LC-Key: {{masterkey}},master" \ "https://API_BASE_URL/1.1/search/analyze?clazz=GameScore&text=响应式设计"
参数包括 clazz 和 text。text 就是测试的文本段,返回结果:
text
{ "tokens": [ { "token": "响应", "start_offset": 0, "end_offset": 2, "type": "word", "position": 0 }, { "token": "式", "start_offset": 2, "end_offset": 3, "type": "word", "position": 1 }, { "token": "设计", "start_offset": 3, "end_offset": 5, "type": "word", "position": 2 } ] }
可以看到,分词系统将「响应式设计」分为了三个词。 如果分词系统认为「响应式设计」是一个词(比如上传了包含「响应式设计」一词的自定义词库),那么返回结果会是:
{ "tokens": [ { "token": "响应式设计", "start_offset": 0, "end_offset": 5, "type": "word", "position": 0 } ] }
全文搜索 REST API 指南
全文搜索服务提供以下 REST API 接口:
在调用全文搜索的 REST API 接口前,需要首先为相应的 Class 启用搜索。 另外也请参考《存储 REST API 使用指南》中关于 API Base URL、请求格式、响应格式的说明,以及《全文搜索开发指南》的《自定义分词》章节。
条件查询
GET /1.1/search/select
REST API 接口提供全文搜索功能。返回类似:
查询的参数支持:
q
skip
limit
sid
fields
highlights
*
,也可以是字段列表逗号隔开的字符串。clazz
include
user,comment
的字符串。仅支持 include Pointer 类型。order
-score,createdAt
逗号隔开的字段,负号表示倒序,可以多个字段组合排序。sort
返回结果属性介绍:
results
:符合查询条件的结果文档。hits
:符合查询条件的文档总数sid
:标记本次查询结果,下次查询继续传入这个 sid 用于查找后续的数据,用来支持翻页查询。返回结果 results 列表里是一个一个的对象,字段是你在全文搜索设置里启用的字段列表,并且有三个特殊字段:
_app_url
:全文搜索结果在网站上的链接。_deeplink
:全文搜索的程序调用 URL,也就是 deeplink。_highlight
: 高亮的搜索结果内容,关键字用em
标签括起来。如果搜索时未传入highlights
参数,则该字段为 null。最外层的
sid
用来标记本次查询结果,下次查询继续传入这个 sid 将翻页查找后 200 条数据:直到返回结果为空。
q 查询语法
q 参数遵循 elasticsearch 的 query string 语法。建议详细阅读这个文档。这里简单做个举例说明。
如果你非常熟悉 elasticsearch 的 query string 语法,那么可以跳至地理位置信息查询一节(地理位置查询是我们在 elasticsearch 上添加的扩展功能)。
查询的关键字保留字符包括:
+ - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
,当出现这些字符的时候,请对这些保留字符做 URL Escape 转义。基础查询语法
可乐
。可口 可乐
,空格隔开,返回的结果默认按照文本相关性排序,其他排序方法请参考上文中的 order 和下文中的 sort。"lady gaga"
,注意用双引号括起来,这样才能保证查询出来的相关对象里的相关内容的关键字也是按照lady gaga
的顺序出现。nickename:逃跑计划
。nickename:"lady gaga"
nickname:(逃跑计划 OR 夜空中最亮的星)
book.name:clojure OR book.content:clojure
,也可以用通配符简写为book.*:clojure
。_missing_:title
。_exists_:title
。上面举例根据字段查询,前提是这些字段在 class 的全文搜索设置里启用了索引。
通配符和正则查询
qu?ck bro*
就是一个通配符查询,?
表示一个单个字符,而*
表示 0 个或者多个字符。通配符其实是正则的简化,可以使用正则查询:
正则的语法参考 正则语法。
模糊查询
根据文本距离相似度(Fuzziness)来查询。例如
quikc~
,默认根据 Damerau-Levenshtein 文本距离算法来查找最多两次变换的匹配项。例如这个查询可以匹配
quick
、qukic
、qukci
等。范围查询
[]
表示闭区间,{}
表示开区间。还可以采用比较运算符:
查询分组
查询可以使用括号分组:
特殊类型字段说明
objectId: 558e20cbe4b060308e3eb36c
,不过这个没有特别必要了,你可以直接走 SDK 查询,效率更好。createdAt:["2015-07-30T00:00:00.000Z" TO "2015-08-15T00:00:00.000Z"]
或者updatedAt: [2012-01-01 TO 2012-12-31]
.iso
后缀做查询:birthday.iso: [2012-01-01 TO 2012-12-31]
字段名.objectId
的方式来查询:player.objectId: 558e20cbe4b060308e3eb36c and player.className: Player
,pointer 只有这两个属性,全文搜索不会 include 其他属性。avartar.url: "https://leancloud.cn/docs/app_search_guide.html#搜索_API"
,无法根据文件内容做全文搜索。复杂排序
假设你要排序的字段是一个数组,比如分数数组
scores
,你想根据平均分来倒序排序,并且没有分数的排最后,那么可以传入:也就是
sort
可以是一个 JSON 数组,其中每个数组元素是一个 JSON 对象:排序的字段作为 key,字段可以设定下列选项:
order
:asc
表示升序,desc
表示降序mode
:如果该字段是多值属性或者数组,那么可以选择按照最小值min
、最大值max
、总和sum
或者平均值avg
来排序。missing
:决定缺失该字段的文档排序在开始还是最后,可以选择_last
或者_first
,或者指定一个默认值。多个字段排序就类似:
地理位置信息查询
如果 class 里某个列是
GeoPoint
类型,那么可以根据这个字段的地理位置远近来排序,例如假设字段location
保存的是GeoPoint
类型,那么查询[39.9, 116.4]
附近的玩家可以通过设定 sort 为:order
和mode
含义跟上述复杂排序里的一致,unit
用来指定距离单位,例如km
表示千米,m
表示米,cm
表示厘米等。moreLikeThis 相关性查询
除了
/1.1/search/select
之外,我们还提供了/1.1/search/mlt
API 接口,用于相似文档的查询,可以用来实现相关性推荐。假设我们有一个 Class 叫
Post
是用来保存博客文章的,我们想基于它的标签字段tags
做相关性推荐:我们设定了
like
参数为clojure
,查询的相关性匹配字段fields
是tags
,也就是从Post
里查找tags
字段跟clojure
这个文本相似的对象,返回类似:除了可以通过指定
like
这样的相关性文本来指定查询相似的文档之外,还可以通过 likeObjectIds 指定一个对象的 objectId 列表,来查询相似的对象:这次我们换成了查找和
577e18b50a2b580057469a5e
这个 objectId 指代的对象相似的对象。更详细的查询参数说明:
clazz
like
likeObjectIds
参数二者必须提供其中之一。代表相似的文本关键字。likeObjectIds
like
参数二者必须提供其中之一。代表相似的对象 objectId 列表,用逗号隔开。min_term_freq
min_doc_freq
max_doc_freq
skip
limit
fields
_all
include
user,comment
的字符串。仅支持 include Pointer 类型。更多内容参考 ElasticSearch 文档。
分词结果查询
全文搜索会对 String 类型的字段自动进行分词处理。 如果发现搜索结果不符合预期,推荐先通过
analyze
API 检查分词结果(要求使用 master key)。analyze
API 也用于验证自定义词库是否生效。参数包括
clazz
和text
。text
就是测试的文本段,返回结果:可以看到,分词系统将「响应式设计」分为了三个词。 如果分词系统认为「响应式设计」是一个词(比如上传了包含「响应式设计」一词的自定义词库),那么返回结果会是: