有用的查询
来源:互联网 发布:设计图软件 编辑:程序博客网 时间:2024/06/04 18:13
例子
基本匹配查询
有两种方式进行基本全文(匹配)查询:使用轻量搜索API,传递的搜索参数是URL的一部分,或者使用完整的JSON请求包,可以在包中使用完整的Elasticsearch DSL。
这里有一个基本匹配查询,要在所有字段中查询字符串“guide”:
GET /bookdb_index/book/_search?q=guide
这个查询的完整JSON包如下,它和上面的搜索API产生相同的结果。
{
"query": {
"multi_match" : {
"query" : "guide",
"fields" : ["_all"]
}
}
}
多匹配关键字适合在一些场景下使用,这些场景里的关键字有一种更方便快捷的形式,特点是可以在多个字段上运行相同的查询。字段属性指定了使用哪些字段查询,在这个例子里,我们要查询文档中的所有字段。
两个API也都允许你指定你想搜索的字段。例如,在书的标题字段中搜索包含“in Action”的:
GET /bookdb_index/book/_search?q=title:in action
但是,在构建更复杂的查询时(稍后我们将看到)以及在指定返回结果的方式时,使用DSL包体可以获得更多的灵活性。在下面的例子里,我们指定了要返回结果的数量、偏移位置(对分页有用)、要返回的字段和高亮显示的项。
POST /bookdb_index/book/_search
{
"query": {
"match" : {
"title" : "in action"
}
},
"size": 2,
"from": 0,
"_source": [ "title", "summary", "publish_date" ],
"highlight": {
"fields" : {
"title" : {}
}
}
}
注意:对于多词查询,相应的匹配查询会让你指定,是否使用and操作符来替代默认的or操作符。你也可以指定minimum_should_match选项来调整返回结果之间的相关性。详情参见Elasticsearch指南。
多字段查找
正如我们所见,为了在一次查找中查询多个字段(例如在title和summary中查找相同的字符串),你使用了multi_match查询。
POST /bookdb_index/book/_search
{
"query": {
"multi_match" : {
"query" : "elasticsearch guide",
"fields": ["title", "summary"]
}
}
}
注意,上面的查询命中了3个结果,因为单词“guide”在摘要中有出现。
提高分值
既然我们正在进行跨多字段的查询,也许想要对某个特定字段提高一些分值。在下面的人为例子中,我们将summary字段的分值提高3倍,有意增加summary字段的重要性,结果是这增强了文档中_id为4那部分的相关性。
POST /bookdb_index/book/_search
{
"query": {
"multi_match" : {
"query" : "elasticsearch guide",
"fields": ["title", "summary^3"]
}
},
"_source": ["title", "summary", "publish_date"]
}
注意:提高分值不仅仅意味着计算得分被增长因子成倍的增加了,实际上提高分值的价值更在于通过它进行规范化和一些内部的优化。关于提高分值如何工作可以近一步参考Elasticsearch指南。
布尔查询
为了获取更多相关且具体的结果,可以用AND/OR/NOT操作符来调整我们的搜索查询请求,在搜索API中则是用布尔查询来实施。布尔查询接收一个must参数(等价于AND)、一个must_not参数(等价于NOT)和一个should参数(等价于OR)。举个例子,比如我想查找一本书,书名里有“Elasticsearch”或“Solr”,且由“clinton gormley”所写,而非“radu gheorge”所写:
POST /bookdb_index/book/_search
{
"query": {
"bool": {
"must": {
"bool" : { "should": [
{ "match": { "title": "Elasticsearch" }},
{ "match": { "title": "Solr" }} ] }
},
"must": { "match": { "authors": "clinton gormely" }},
"must_not": { "match": {"authors": "radu gheorge" }}
}
}
}
注意:正如你所见,布尔查询能够包装任何查询类型,包括其他的布尔查询,用以创建任意复杂的或者深度嵌套的查询。
模糊查询
在进行匹配和多项匹配时,可以启用模糊匹配来捕捉拼写错误,模糊度是基于原始单词的编辑距离来指定的。
POST /bookdb_index/book/_search
{
"query": {
"multi_match" : {
"query" : "comprihensiv guide",
"fields": ["title", "summary"],
"fuzziness": "AUTO"
}
},
"_source": ["title", "summary", "publish_date"],
"size": 1
}
注:当术语长度大于5个字符时,"AUTO"的模糊值等同于指定值“2”。但是,80%的人类拼写错误的编辑距离为1,所以,将模糊值设置为“1”可能会提高您的整体搜索性能。更多详细信息,请参阅Elasticsearch指南中的“排版和拼写错误”(Typos and Misspellings)章节。
通配符查询
通配符查询允许你指定匹配的模式,而不是整个术语。? 匹配任何字符,*匹配零个或多个字符。例如,要查找名称以字母't'开头的所有作者的记录:
POST /bookdb_index/book/_search
{
"query": {
"wildcard" : {
"authors" : "t*"
}
},
"_source": ["title", "authors"],
"highlight": {
"fields" : {
"authors" : {}
}
}
}
正则查询
正则查询让你可以使用比通配符更复杂的模式进行查询:
POST /bookdb_index/book/_search
{
"query": {
"regexp" : {
"authors" : "t[a-z]*y"
}
},
"_source": ["title", "authors"],
"highlight": {
"fields" : {
"authors" : {}
}
}
}
整句查询
整句查询要求在请求字符串中的所有查询项必须都在文档中存在,文中顺序也得和请求字符串一致,且彼此相连。默认情况下,查询项之间必须紧密相连,但可以设置slop值来指定查询项之间可以分隔多远的距离,结果仍将被当作一次成功的匹配。
POST /bookdb_index/book/_search
{
"query": {
"multi_match" : {
"query": "search engine",
"fields": ["title", "summary"],
"type": "phrase",
"slop": 3
}
},
"_source": [ "title", "summary", "publish_date" ]
}
注意:在上述例子中,对于非整句类型的查询,_id为1的文档一般会比_id为4的文档得分高,结果位置也更靠前,因为它的字段长度较短,但是对于整句类型查询,由于查询项之间的接近程度是一个计算因素,因此_id为4的文档得分更高。
短语前缀式查询
短语前缀式查询能够进行“即时搜索”(search-as-you-type)类型的匹配,或者说提供一个查询时的初级自动补全功能,无需以任何方式备全你的数据。和match_phrase查询类似,它也接收slop参数,用来调整单词顺序和不太严格的相对位置,它还接收max_expansions参数,用来限制查询项的数量,降低对资源需求的强度。
注意:采用“查询时即时搜索”具有较大的性能成本,更好的解决方案是采用“索引时即时搜索”。更多信息,请查看自动补齐 API(Completion Suggester API)或边缘分词器(Edge-Ngram filters)的用法。
请求字符串
请求字符串类型(query_string)的查询提供了一个方法,用简洁的简写语法来执行多匹配查询、布尔查询、提权查询、模糊查询、通配符查询、正则查询和范围查询。下面的例子中,我们在那些作者是“grant ingersoll”或“tom morton”的某本书当中,使用查询项“search algorithm”进行一次模糊查询,搜索全部字段,但给摘要字段的权重提升2倍。
POST /bookdb_index/book/_search
{
"query": {
"query_string" : {
"query": "(saerch~1 algorithm~1) AND (grant ingersoll) OR (tom morton)",
"fields": ["_all", "summary^2"]
}
},
"_source": [ "title", "summary", "authors" ],
"highlight": {
"fields" : {
"summary" : {}
}
}
}
简单请求字符串
简单请求字符串类型(simple_query_string)的查询是请求字符串类型(query_string)查询的一个版本,它更适合那种仅暴露给用户一个简单搜索框的场景,因为,它用+/|/-分别替换了AND/OR/NOT,并且自动丢弃了请求中无效的部分,不会在用户犯错时抛出异常。
POST /bookdb_index/book/_search
{
"query": {
"simple_query_string" : {
"query": "(saerch~1 algorithm~1) + (grant ingersoll) | (tom morton)",
"fields": ["_all", "summary^2"]
}
},
"_source": [ "title", "summary", "authors" ],
"highlight": {
"fields" : {
"summary" : {}
}
}
}
词条/多词条查询
以上例子均为全文检索的示例。有时我们对结构化查询更感兴趣,希望得到更准确的匹配并返回结果,词条查询和多词条查询可帮我们实现。在下面的例子中,我们要在索引中找到所有由曼宁出版社出版的图书。
POST /bookdb_index/book/_search
{
"query": {
"term" : {
"publisher": "manning"
}
},
"_source" : ["title","publish_date","publisher"]
}
可使用词条关键字来指定多个词条,将搜索项用数组传入。
{
"query": {
"terms" : {
"publisher": ["oreilly", "packt"]
}
}
}
词条查询 - 排序
词条查询的结果(和其他查询结果一样)可以被轻易排序,多级排序也被允许。
POST /bookdb_index/book/_search
{
"query": {
"term" : {
"publisher": "manning"
}
},
"_source" : ["title","publish_date","publisher"],
"sort": [
{ "publish_date": {"order":"desc"}},
{ "title": { "order": "desc" }}
]
}
范围查询
另一个结构化查询的例子是范围查询。在这个例子中,我们要查找2015年出版的书。
POST /bookdb_index/book/_search
{
"query": {
"range" : {
"publish_date": {
"gte": "2015-01-01",
"lte": "2015-12-31"
}
}
},
"_source" : ["title","publish_date","publisher"]
}
注意:范围查询作用于日期、数字和字符串类型的字段。
过滤查询
过滤查询让你可以过滤查询结果,对于我们的这个示例,要在标题或摘要中检索一些书,查询项为“Elasticsearch”,但我们又想筛出那些仅有20个以上评论的。
POST /bookdb_index/book/_search
{
"query": {
"filtered": {
"query" : {
"multi_match": {
"query": "elasticsearch",
"fields": ["title","summary"]
}
},
"filter": {
"range" : {
"num_reviews": {
"gte": 20
}
}
}
}
},
"_source" : ["title","summary","publisher", "num_reviews"]
}
注意:过滤查询并不强制它作用于其上的查询必须存在,如果未指定查询,那么过滤将作用于match_all查询,match_all基本上会返回索引内的全部文档。实际上,过滤只在第一次运行,以减少所需的查询面积,并且,在第一次使用后过滤会被缓存,大大提高了性能。
多重过滤
多重过滤可以结合布尔查询使用,下一个例子中,过滤查询决定只返回那些包含至少20条评论,且必须在2015年前出版,且由oreilly出版的结果。
POST /bookdb_index/book/_search
{
"query": {
"filtered": {
"query" : {
"multi_match": {
"query": "elasticsearch",
"fields": ["title","summary"]
}
},
"filter": {
"bool": {
"must": {
"range" : { "num_reviews": { "gte": 20 } }
},
"must_not": {
"range" : { "publish_date": { "lte": "2014-12-31" } }
},
"should": {
"term": { "publisher": "oreilly" }
}
}
}
}
},
"_source" : ["title","summary","publisher", "num_reviews", "publish_date"]
}
作用分值: 域值因子
也许在某种情况下,你想把文档中的某个特定域作为计算相关性分值的一个因素,比较典型的场景是你想根据普及程度来提高一个文档的相关性。在我们的示例中,我们想把最受欢迎的书(基于评论数判断)的权重进行提高,可使用field_value_factor用以影响分值。
POST /bookdb_index/book/_search
{
"query": {
"function_score": {
"query": {
"multi_match" : {
"query" : "search engine",
"fields": ["title", "summary"]
}
},
"field_value_factor": {
"field" : "num_reviews",
"modifier": "log1p",
"factor" : 2
}
}
},
"_source": ["title", "summary", "publish_date", "num_reviews"]
}
注意 1: 我们可能刚运行了一个常规的多匹配查询,并对num_reviews域进行了排序,这让我们失去了评估相关性分值的好处。
注意 2: 有大量的附加参数可用来调整提升原始相关性分值效果的程度,比如“modifier”, “factor”, “boost_mode”等等,至于细节可在Elasticsearch指南中探索。
作用分值: 衰变函数
假设不想使用域值做递增提升,而你有一个理想目标值,并希望用这个加权因子来对这个离你较远的目标值进行衰减。有个典型的用途是基于经纬度,或是像价格、日期等数值域的提升。在如下的人造例子中,我们查找出版日期大约在2014年6月左右,查询项是“搜索引擎”(“search engines”)的书。
POST /bookdb_index/book/_search
{
"query": {
"function_score": {
"query": {
"multi_match" : {
"query" : "search engine",
"fields": ["title", "summary"]
}
},
"functions": [
{
"exp": {
"publish_date" : {
"origin": "2014-06-15",
"offset": "7d",
"scale" : "30d"
}
}
}
],
"boost_mode" : "replace"
}
},
"_source": ["title", "summary", "publish_date", "num_reviews"]
}
作用分值: 脚本评分
当内置的评分函数无法满足你的需求时,还有一个选择是用Groovy脚本。在我们的例子中,想要指定一个脚本,能在决定把评论数量的因素计算多少之前,先将publish_date考虑在内。因为很新的书也许不会有多少评论数,分值不应该被惩罚。
评分脚本如下:
publish_date = doc['publish_date'].value
num_reviews = doc['num_reviews'].value
if (publish_date > Date.parse('yyyy-MM-dd', threshold).getTime()) {
my_score = Math.log(2.5 + num_reviews)
} else {
my_score = Math.log(1 + num_reviews)
}
return my_score
在script_score参数内动态调用评分脚本:
POST /bookdb_index/book/_search
{
"query": {
"function_score": {
"query": {
"multi_match" : {
"query" : "search engine",
"fields": ["title", "summary"]
}
},
"functions": [
{
"script_score": {
"params" : {
"threshold": "2015-07-30"
},
"script": "publish_date = doc['publish_date'].value; num_reviews = doc['num_reviews'].value; if (publish_date > Date.parse('yyyy-MM-dd', threshold).getTime()) { return log(2.5 + num_reviews) }; return log(1 + num_reviews);"
}
}
]
}
},
"_source": ["title", "summary", "publish_date", "num_reviews"]
}
注意 1: 要在ES实例中使用动态脚本,必须在config/elasticsearch.yaml文件中enable它,也可以使用存储在ES服务器上的脚本。建议看看Elasticsearch指南文档获取更多信息。
注意 2: 因JSON不能包含嵌入式换行符,请使用分号来分割语句。
基本匹配查询
有两种方式进行基本全文(匹配)查询:使用轻量搜索API,传递的搜索参数是URL的一部分,或者使用完整的JSON请求包,可以在包中使用完整的Elasticsearch DSL。
这里有一个基本匹配查询,要在所有字段中查询字符串“guide”:
GET /bookdb_index/book/_search?q=guide
这个查询的完整JSON包如下,它和上面的搜索API产生相同的结果。
{
"query": {
"multi_match" : {
"query" : "guide",
"fields" : ["_all"]
}
}
}
多匹配关键字适合在一些场景下使用,这些场景里的关键字有一种更方便快捷的形式,特点是可以在多个字段上运行相同的查询。字段属性指定了使用哪些字段查询,在这个例子里,我们要查询文档中的所有字段。
两个API也都允许你指定你想搜索的字段。例如,在书的标题字段中搜索包含“in Action”的:
GET /bookdb_index/book/_search?q=title:in action
但是,在构建更复杂的查询时(稍后我们将看到)以及在指定返回结果的方式时,使用DSL包体可以获得更多的灵活性。在下面的例子里,我们指定了要返回结果的数量、偏移位置(对分页有用)、要返回的字段和高亮显示的项。
POST /bookdb_index/book/_search
{
"query": {
"match" : {
"title" : "in action"
}
},
"size": 2,
"from": 0,
"_source": [ "title", "summary", "publish_date" ],
"highlight": {
"fields" : {
"title" : {}
}
}
}
注意:对于多词查询,相应的匹配查询会让你指定,是否使用and操作符来替代默认的or操作符。你也可以指定minimum_should_match选项来调整返回结果之间的相关性。详情参见Elasticsearch指南。
多字段查找
正如我们所见,为了在一次查找中查询多个字段(例如在title和summary中查找相同的字符串),你使用了multi_match查询。
POST /bookdb_index/book/_search
{
"query": {
"multi_match" : {
"query" : "elasticsearch guide",
"fields": ["title", "summary"]
}
}
}
注意,上面的查询命中了3个结果,因为单词“guide”在摘要中有出现。
提高分值
既然我们正在进行跨多字段的查询,也许想要对某个特定字段提高一些分值。在下面的人为例子中,我们将summary字段的分值提高3倍,有意增加summary字段的重要性,结果是这增强了文档中_id为4那部分的相关性。
POST /bookdb_index/book/_search
{
"query": {
"multi_match" : {
"query" : "elasticsearch guide",
"fields": ["title", "summary^3"]
}
},
"_source": ["title", "summary", "publish_date"]
}
注意:提高分值不仅仅意味着计算得分被增长因子成倍的增加了,实际上提高分值的价值更在于通过它进行规范化和一些内部的优化。关于提高分值如何工作可以近一步参考Elasticsearch指南。
布尔查询
为了获取更多相关且具体的结果,可以用AND/OR/NOT操作符来调整我们的搜索查询请求,在搜索API中则是用布尔查询来实施。布尔查询接收一个must参数(等价于AND)、一个must_not参数(等价于NOT)和一个should参数(等价于OR)。举个例子,比如我想查找一本书,书名里有“Elasticsearch”或“Solr”,且由“clinton gormley”所写,而非“radu gheorge”所写:
POST /bookdb_index/book/_search
{
"query": {
"bool": {
"must": {
"bool" : { "should": [
{ "match": { "title": "Elasticsearch" }},
{ "match": { "title": "Solr" }} ] }
},
"must": { "match": { "authors": "clinton gormely" }},
"must_not": { "match": {"authors": "radu gheorge" }}
}
}
}
注意:正如你所见,布尔查询能够包装任何查询类型,包括其他的布尔查询,用以创建任意复杂的或者深度嵌套的查询。
模糊查询
在进行匹配和多项匹配时,可以启用模糊匹配来捕捉拼写错误,模糊度是基于原始单词的编辑距离来指定的。
POST /bookdb_index/book/_search
{
"query": {
"multi_match" : {
"query" : "comprihensiv guide",
"fields": ["title", "summary"],
"fuzziness": "AUTO"
}
},
"_source": ["title", "summary", "publish_date"],
"size": 1
}
注:当术语长度大于5个字符时,"AUTO"的模糊值等同于指定值“2”。但是,80%的人类拼写错误的编辑距离为1,所以,将模糊值设置为“1”可能会提高您的整体搜索性能。更多详细信息,请参阅Elasticsearch指南中的“排版和拼写错误”(Typos and Misspellings)章节。
通配符查询
通配符查询允许你指定匹配的模式,而不是整个术语。? 匹配任何字符,*匹配零个或多个字符。例如,要查找名称以字母't'开头的所有作者的记录:
POST /bookdb_index/book/_search
{
"query": {
"wildcard" : {
"authors" : "t*"
}
},
"_source": ["title", "authors"],
"highlight": {
"fields" : {
"authors" : {}
}
}
}
正则查询
正则查询让你可以使用比通配符更复杂的模式进行查询:
POST /bookdb_index/book/_search
{
"query": {
"regexp" : {
"authors" : "t[a-z]*y"
}
},
"_source": ["title", "authors"],
"highlight": {
"fields" : {
"authors" : {}
}
}
}
整句查询
整句查询要求在请求字符串中的所有查询项必须都在文档中存在,文中顺序也得和请求字符串一致,且彼此相连。默认情况下,查询项之间必须紧密相连,但可以设置slop值来指定查询项之间可以分隔多远的距离,结果仍将被当作一次成功的匹配。
POST /bookdb_index/book/_search
{
"query": {
"multi_match" : {
"query": "search engine",
"fields": ["title", "summary"],
"type": "phrase",
"slop": 3
}
},
"_source": [ "title", "summary", "publish_date" ]
}
注意:在上述例子中,对于非整句类型的查询,_id为1的文档一般会比_id为4的文档得分高,结果位置也更靠前,因为它的字段长度较短,但是对于整句类型查询,由于查询项之间的接近程度是一个计算因素,因此_id为4的文档得分更高。
短语前缀式查询
短语前缀式查询能够进行“即时搜索”(search-as-you-type)类型的匹配,或者说提供一个查询时的初级自动补全功能,无需以任何方式备全你的数据。和match_phrase查询类似,它也接收slop参数,用来调整单词顺序和不太严格的相对位置,它还接收max_expansions参数,用来限制查询项的数量,降低对资源需求的强度。
注意:采用“查询时即时搜索”具有较大的性能成本,更好的解决方案是采用“索引时即时搜索”。更多信息,请查看自动补齐 API(Completion Suggester API)或边缘分词器(Edge-Ngram filters)的用法。
请求字符串
请求字符串类型(query_string)的查询提供了一个方法,用简洁的简写语法来执行多匹配查询、布尔查询、提权查询、模糊查询、通配符查询、正则查询和范围查询。下面的例子中,我们在那些作者是“grant ingersoll”或“tom morton”的某本书当中,使用查询项“search algorithm”进行一次模糊查询,搜索全部字段,但给摘要字段的权重提升2倍。
POST /bookdb_index/book/_search
{
"query": {
"query_string" : {
"query": "(saerch~1 algorithm~1) AND (grant ingersoll) OR (tom morton)",
"fields": ["_all", "summary^2"]
}
},
"_source": [ "title", "summary", "authors" ],
"highlight": {
"fields" : {
"summary" : {}
}
}
}
简单请求字符串
简单请求字符串类型(simple_query_string)的查询是请求字符串类型(query_string)查询的一个版本,它更适合那种仅暴露给用户一个简单搜索框的场景,因为,它用+/|/-分别替换了AND/OR/NOT,并且自动丢弃了请求中无效的部分,不会在用户犯错时抛出异常。
POST /bookdb_index/book/_search
{
"query": {
"simple_query_string" : {
"query": "(saerch~1 algorithm~1) + (grant ingersoll) | (tom morton)",
"fields": ["_all", "summary^2"]
}
},
"_source": [ "title", "summary", "authors" ],
"highlight": {
"fields" : {
"summary" : {}
}
}
}
词条/多词条查询
以上例子均为全文检索的示例。有时我们对结构化查询更感兴趣,希望得到更准确的匹配并返回结果,词条查询和多词条查询可帮我们实现。在下面的例子中,我们要在索引中找到所有由曼宁出版社出版的图书。
POST /bookdb_index/book/_search
{
"query": {
"term" : {
"publisher": "manning"
}
},
"_source" : ["title","publish_date","publisher"]
}
可使用词条关键字来指定多个词条,将搜索项用数组传入。
{
"query": {
"terms" : {
"publisher": ["oreilly", "packt"]
}
}
}
词条查询 - 排序
词条查询的结果(和其他查询结果一样)可以被轻易排序,多级排序也被允许。
POST /bookdb_index/book/_search
{
"query": {
"term" : {
"publisher": "manning"
}
},
"_source" : ["title","publish_date","publisher"],
"sort": [
{ "publish_date": {"order":"desc"}},
{ "title": { "order": "desc" }}
]
}
范围查询
另一个结构化查询的例子是范围查询。在这个例子中,我们要查找2015年出版的书。
POST /bookdb_index/book/_search
{
"query": {
"range" : {
"publish_date": {
"gte": "2015-01-01",
"lte": "2015-12-31"
}
}
},
"_source" : ["title","publish_date","publisher"]
}
注意:范围查询作用于日期、数字和字符串类型的字段。
过滤查询
过滤查询让你可以过滤查询结果,对于我们的这个示例,要在标题或摘要中检索一些书,查询项为“Elasticsearch”,但我们又想筛出那些仅有20个以上评论的。
POST /bookdb_index/book/_search
{
"query": {
"filtered": {
"query" : {
"multi_match": {
"query": "elasticsearch",
"fields": ["title","summary"]
}
},
"filter": {
"range" : {
"num_reviews": {
"gte": 20
}
}
}
}
},
"_source" : ["title","summary","publisher", "num_reviews"]
}
注意:过滤查询并不强制它作用于其上的查询必须存在,如果未指定查询,那么过滤将作用于match_all查询,match_all基本上会返回索引内的全部文档。实际上,过滤只在第一次运行,以减少所需的查询面积,并且,在第一次使用后过滤会被缓存,大大提高了性能。
多重过滤
多重过滤可以结合布尔查询使用,下一个例子中,过滤查询决定只返回那些包含至少20条评论,且必须在2015年前出版,且由oreilly出版的结果。
POST /bookdb_index/book/_search
{
"query": {
"filtered": {
"query" : {
"multi_match": {
"query": "elasticsearch",
"fields": ["title","summary"]
}
},
"filter": {
"bool": {
"must": {
"range" : { "num_reviews": { "gte": 20 } }
},
"must_not": {
"range" : { "publish_date": { "lte": "2014-12-31" } }
},
"should": {
"term": { "publisher": "oreilly" }
}
}
}
}
},
"_source" : ["title","summary","publisher", "num_reviews", "publish_date"]
}
作用分值: 域值因子
也许在某种情况下,你想把文档中的某个特定域作为计算相关性分值的一个因素,比较典型的场景是你想根据普及程度来提高一个文档的相关性。在我们的示例中,我们想把最受欢迎的书(基于评论数判断)的权重进行提高,可使用field_value_factor用以影响分值。
POST /bookdb_index/book/_search
{
"query": {
"function_score": {
"query": {
"multi_match" : {
"query" : "search engine",
"fields": ["title", "summary"]
}
},
"field_value_factor": {
"field" : "num_reviews",
"modifier": "log1p",
"factor" : 2
}
}
},
"_source": ["title", "summary", "publish_date", "num_reviews"]
}
注意 1: 我们可能刚运行了一个常规的多匹配查询,并对num_reviews域进行了排序,这让我们失去了评估相关性分值的好处。
注意 2: 有大量的附加参数可用来调整提升原始相关性分值效果的程度,比如“modifier”, “factor”, “boost_mode”等等,至于细节可在Elasticsearch指南中探索。
作用分值: 衰变函数
假设不想使用域值做递增提升,而你有一个理想目标值,并希望用这个加权因子来对这个离你较远的目标值进行衰减。有个典型的用途是基于经纬度,或是像价格、日期等数值域的提升。在如下的人造例子中,我们查找出版日期大约在2014年6月左右,查询项是“搜索引擎”(“search engines”)的书。
POST /bookdb_index/book/_search
{
"query": {
"function_score": {
"query": {
"multi_match" : {
"query" : "search engine",
"fields": ["title", "summary"]
}
},
"functions": [
{
"exp": {
"publish_date" : {
"origin": "2014-06-15",
"offset": "7d",
"scale" : "30d"
}
}
}
],
"boost_mode" : "replace"
}
},
"_source": ["title", "summary", "publish_date", "num_reviews"]
}
作用分值: 脚本评分
当内置的评分函数无法满足你的需求时,还有一个选择是用Groovy脚本。在我们的例子中,想要指定一个脚本,能在决定把评论数量的因素计算多少之前,先将publish_date考虑在内。因为很新的书也许不会有多少评论数,分值不应该被惩罚。
评分脚本如下:
publish_date = doc['publish_date'].value
num_reviews = doc['num_reviews'].value
if (publish_date > Date.parse('yyyy-MM-dd', threshold).getTime()) {
my_score = Math.log(2.5 + num_reviews)
} else {
my_score = Math.log(1 + num_reviews)
}
return my_score
在script_score参数内动态调用评分脚本:
POST /bookdb_index/book/_search
{
"query": {
"function_score": {
"query": {
"multi_match" : {
"query" : "search engine",
"fields": ["title", "summary"]
}
},
"functions": [
{
"script_score": {
"params" : {
"threshold": "2015-07-30"
},
"script": "publish_date = doc['publish_date'].value; num_reviews = doc['num_reviews'].value; if (publish_date > Date.parse('yyyy-MM-dd', threshold).getTime()) { return log(2.5 + num_reviews) }; return log(1 + num_reviews);"
}
}
]
}
},
"_source": ["title", "summary", "publish_date", "num_reviews"]
}
注意 1: 要在ES实例中使用动态脚本,必须在config/elasticsearch.yaml文件中enable它,也可以使用存储在ES服务器上的脚本。建议看看Elasticsearch指南文档获取更多信息。
注意 2: 因JSON不能包含嵌入式换行符,请使用分号来分割语句。
阅读全文
0 0
- 有用的Oracle查询
- 有用的查询
- 超有用的sql查询语句。项目、面试都有用
- SQL的有用的系统查询
- 一些比较有用的oracle查询语句
- SQL 一些有用的查询语句积累
- 非常有用的oracle查询语句
- (HQL)hibernate查询语言非常有用的
- 几个有用的oracle dba_hist_*查询语句
- oracle中非常有用的查询语句
- 非常有用的 Oracle 查询语句
- 两个分析查询的有用函数
- 非常有用的 Oracle 查询语句
- 45个非常有用的查询语句
- 有用的SQL高级函数与查询
- mongodb比较有用的查询技巧
- 非常有用的 Oracle 查询语句
- oracle子递归查询语句的几个有用的属性
- 无法识别的属性“targetFramework”。请注意属性名称区分大小写。错误解决办法
- Python之Scrapy爬虫框架安装及简单使用
- 设置环境变量快捷方式
- linux之getopt 函数
- JRebel热部署
- 有用的查询
- Carthage 教程:开始
- 如何让已经收录的内容更有seo价值
- 带抽屉的困难版
- jsoup获取页面内容
- 多线程(三)
- HTTP Status400的原因
- Android内存泄漏产生的原因以及解决方案(OOM)
- AKKA路由策略