search(7)- elastic4s-search-filter模式
现在我们可以开始探讨ES的核心环节:搜索search了。search又分filter,query两种模式。filter模式即筛选模式:将符合筛选条件的记录作为结果找出来。query模式则分两个步骤:先筛选,然后对每条符合条件记录进行相似度计算。就是多了个评分过程。如果我们首先要实现传统数据库的查询功能的话,那么用filter模式就足够了。filter模式同样可以利用搜索引擎的分词功能产生高质量的查询结果,而且filter是可以进缓存的,执行起来效率更高。这些功能数据库管理系统是无法达到的。ES的filter模式是在bool查询框架下实现的,如下:
GET /_search
{
"query": {
"bool": {
"filter": [
{ "term": { "status": "published" }},
{ "range": { "publish_date": { "gte": "2015-01-01" }}}
]
}
}
}
下面是一个最简单的示范:
val filterTerm = search("bank")
.query(
boolQuery().filter(termQuery("city.keyword","Brogan")))
产生的请求json如下:
POST /bank/_search
{
"query":{
"bool":{
"filter":[
{
"term":{"city.keyword":{"value":"Brogan"}}
}
]
}
}
}
先说明一下这个查询请求:这是一个词条查询termQuery,要求条件完全匹配,包括大小写,肯定无法用经过分词器分析过的字段,所以用city.keyword。
返回查询结果json:
{
"took" : ,
"timed_out" : false,
"_shards" : {
"total" : ,
"successful" : ,
"skipped" : ,
"failed" :
},
"hits" : {
"total" : {
"value" : ,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [
{
"_index" : "bank",
"_type" : "_doc",
"_id" : "",
"_score" : 0.0,
"_source" : {
"account_number" : ,
"balance" : ,
"firstname" : "Amber",
"lastname" : "Duke",
"age" : ,
"gender" : "M",
"address" : "880 Holmes Lane",
"employer" : "Pyrami",
"email" : "amberduke@pyrami.com",
"city" : "Brogan",
"state" : "IL"
}
}
]
}
}
我们来看看elasitic4s是怎样表达上面json结果的:首先,返回的类型是 Reponse[SearchResponse]。Response类定义如下:
sealed trait Response[+U] {
def status: Int // the http status code of the response
def body: Option[String] // the http response body if the response included one
def headers: Map[String, String] // any http headers included in the response
def result: U // returns the marshalled response U or throws an exception
def error: ElasticError // returns the error or throw an exception
def isError: Boolean // returns true if this is an error response
final def isSuccess: Boolean = !isError // returns true if this is a success
def map[V](f: U => V): Response[V]
def flatMap[V](f: U => Response[V]): Response[V]
final def fold[V](ifError: => V)(f: U => V): V = if (isError) ifError else f(result)
final def fold[V](onError: RequestFailure => V, onSuccess: U => V): V = this match {
case failure: RequestFailure => onError(failure)
case RequestSuccess(_, _, _, result) => onSuccess(result)
}
final def foreach[V](f: U => V): Unit = if (!isError) f(result)
final def toOption: Option[U] = if (isError) None else Some(result)
}
Response[+U]是个高阶类,如果把U替换成SearchResponse, 那么返回的结果值可以用def result: SearchResponse来获取。status代表标准HTTP返回状态,isError,isSuccess代表执行情况,error是确切的异常消息。返回结果的头部信息在headers内。我们再看看这个SearchResponse类的定义:
case class SearchResponse(took: Long,
@JsonProperty("timed_out") isTimedOut: Boolean,
@JsonProperty("terminated_early") isTerminatedEarly: Boolean,
private val suggest: Map[String, Seq[SuggestionResult]],
@JsonProperty("_shards") private val _shards: Shards,
@JsonProperty("_scroll_id") scrollId: Option[String],
@JsonProperty("aggregations") private val _aggregationsAsMap: Map[String, Any],
hits: SearchHits) {...} case class SearchHits(total: Total,
@JsonProperty("max_score") maxScore: Double,
hits: Array[SearchHit]) {
def size: Long = hits.length
def isEmpty: Boolean = hits.isEmpty
def nonEmpty: Boolean = hits.nonEmpty
} case class SearchHit(@JsonProperty("_id") id: String,
@JsonProperty("_index") index: String,
@JsonProperty("_type") `type`: String,
@JsonProperty("_version") version: Long,
@JsonProperty("_seq_no") seqNo: Long,
@JsonProperty("_primary_term") primaryTerm: Long,
@JsonProperty("_score") score: Float,
@JsonProperty("_parent") parent: Option[String],
@JsonProperty("_shard") shard: Option[String],
@JsonProperty("_node") node: Option[String],
@JsonProperty("_routing") routing: Option[String],
@JsonProperty("_explanation") explanation: Option[Explanation],
@JsonProperty("sort") sort: Option[Seq[AnyRef]],
private val _source: Map[String, AnyRef],
fields: Map[String, AnyRef],
@JsonProperty("highlight") private val _highlight: Option[Map[String, Seq[String]]],
private val inner_hits: Map[String, Map[String, Any]],
@JsonProperty("matched_queries") matchedQueries: Option[Set[String]])
extends Hit {...}
返回结果的重要部分如 _score, _source,fields都在SearchHit里。完整的返回结果处理示范如下:
val filterTerm = client.execute(search("bank")
.query(
boolQuery().filter(termQuery("city.keyword","Brogan")))).await
if (filterTerm.isSuccess) {
if (filterTerm.result.nonEmpty)
filterTerm.result.hits.hits.foreach {hit => println(hit.sourceAsMap)}
} else println(s"Error: ${filterTerm.error.reason}")
传统查询方式中前缀查询用的比较多:
POST /bank/_search
{
"query":{
"bool":{
"filter":[
{
"prefix":{"city.keyword":{"value":"Bro"}}
}
]
}
}
} val filterPrifix = client.execute(search("bank")
.query(
boolQuery().filter(prefixQuery("city.keyword","Bro")))
.sourceInclude("address","city","state")
).await
if (filterPrifix.isSuccess) {
if (filterPrifix.result.nonEmpty)
filterPrifix.result.hits.hits.foreach {hit => println(hit.sourceAsMap)}
} else println(s"Error: ${filterPrifix.error.reason}") .... Map(address -> Holmes Lane, city -> Brogan, state -> IL)
Map(address -> Nostrand Avenue, city -> Brooktrails, state -> GA)
Map(address -> Whitty Lane, city -> Broadlands, state -> VT)
Map(address -> Heath Place, city -> Brookfield, state -> OK)
Map(address -> Bridge Street, city -> Brownlee, state -> HI)
Map(address -> Pierrepont Place, city -> Brownsville, state -> MI)
正则表达式查询也有:
POST /bank/_search
{
"query":{
"bool":{
"filter":[
{
"regexp":{"address.keyword":{"value":".*bridge.*"}}
}
]
}
}
} val filterRegex = client.execute(search("bank")
.query(
boolQuery().filter(regexQuery("address.keyword",".*bridge.*")))
.sourceInclude("address","city","state")
).await
if (filterRegex.isSuccess) {
if (filterRegex.result.nonEmpty)
filterRegex.result.hits.hits.foreach {hit => println(hit.sourceAsMap)}
} else println(s"Error: ${filterRegex.error.reason}") ....
Map(address -> Bainbridge Street, city -> Elizaville, state -> MS)
Map(address -> Cambridge Place, city -> Efland, state -> ID)
当然,ES用bool查询来实现复合式查询,我们可以把一个bool查询放进filter框架,如下:
POST /bank/_search
{
"query":{
"bool":{
"filter":[
{
"regexp":{"address.keyword":{"value":".*bridge.*"}}
},
{
"bool": {
"must": [
{ "match" : {"lastname" : "lane"}}
]
}
}
]
}
}
}
elastic4s QueryDSL 语句和返回结果如下:
val filterBool = client.execute(search("bank")
.query(
boolQuery().filter(regexQuery("address.keyword",".*bridge.*"),
boolQuery().must(matchQuery("lastname","lane"))))
.sourceInclude("lastname","address","city","state")
).await
if (filterBool.isSuccess) {
if (filterBool.result.nonEmpty)
filterBool.result.hits.hits.foreach {hit => println(s"score: ${hit.score}, ${hit.sourceAsMap}")}
} else println(s"Error: ${filterBool.error.reason}")
...
score: 0.0, Map(address -> Bainbridge Street, city -> Elizaville, state -> MS, lastname -> Lane)
score: 0.0 ,说明filter不会进行评分。可能执行效率会有所提高吧。
search(7)- elastic4s-search-filter模式的更多相关文章
- 1.3 正则表达式和Python语言-1.3.5使用 search()在一个字符串中查找模式(搜索与匹配 的对比)
1.3.5 使用 search()在一个字符串中查找模式(搜索与匹配的对比) 其实,想要搜索的模式出现在一个字符串中间部分的概率,远大于出现在字符串起始部分的概率.这也就是 search()派上用场的 ...
- Comparing randomized search and grid search for hyperparameter estimation
Comparing randomized search and grid search for hyperparameter estimation Compare randomized search ...
- 【起航计划 032】2015 起航计划 Android APIDemo的魔鬼步伐 31 App->Search->Invoke Search 搜索功能 Search Dialog SearchView SearchRecentSuggestions
Search (搜索)是Android平台的一个核心功能之一,用户可以在手机搜索在线的或是本地的信息.Android平台为所有需要提供搜索或是查询功能的应用提 供了一个统一的Search Framew ...
- search(8)- elastic4s-search-query模式
上篇提过query模式除对记录的筛选之外还对符合条件的记录进行了评分,即与条件的相似匹配程度.我们把评分放在后面的博文中讨论,这篇我们只介绍query查询. 查询可以分为绝对值查询和全文查询:绝对值查 ...
- [Math] Beating the binary search algorithm – interpolation search, galloping search
From: http://blog.jobbole.com/73517/ 二分检索是查找有序数组最简单然而最有效的算法之一.现在的问题是,更复杂的算法能不能做的更好?我们先看一下其他方法. 有些情况下 ...
- LeetCode:Search Insert Position,Search for a Range (二分查找,lower_bound,upper_bound)
Search Insert Position Given a sorted array and a target value, return the index if the target is fo ...
- leetcode 704. Binary Search 、35. Search Insert Position 、278. First Bad Version
704. Binary Search 1.使用start+1 < end,这样保证最后剩两个数 2.mid = start + (end - start)/2,这样避免接近max-int导致的溢 ...
- Depth-first search and Breadth-first search 深度优先搜索和广度优先搜索
Depth-first search Depth-first search (DFS) is an algorithm for traversing or searching tree or grap ...
- [Algorithm] Beating the Binary Search algorithm – Interpolation Search, Galloping Search
From: http://blog.jobbole.com/73517/ 二分检索是查找有序数组最简单然而最有效的算法之一.现在的问题是,更复杂的算法能不能做的更好?我们先看一下其他方法. 有些情况下 ...
随机推荐
- ClickHouse学习系列之一【安装说明】
背景 最近花了些时间看了下ClickHouse文档,发现它在OLAP方面表现很优异,而且相对也比较轻量和简单,所以准备入门了解下该数据库系统.按照习惯第一步先安装,本文对其用户权限管理方面进行梳理说明 ...
- html-css:浮动_清除浮动
1.浮动 清除浮动之前我们首先需要了解为什么要清除浮动 1. 假设我们有一个父盒子,不设置高度,其高度有内部子盒子的大小自动撑开,这样是完全可行的,因为有时候我们并不想直接固定死父盒子的大小,而是根据 ...
- jsonp跨域的原理及实现
1,什么是跨域? 跨域跨域,跨过域名,笼统来说就是一个域名区请求另外一个域名的数据,但实际上,不同端口.不同域名.不同协议上请求数据都会出现跨域问题.浏览器出于安全考虑会报出异常,拒绝访问. 2,js ...
- python—异常处理try
写代码的时候会遇到各种各样的异常,那么代码就不会继续往下走了.比如说10除以0是错误的,因为除数不能为零学会捕捉异常,在异常出现的时候我们要做什么操作. 捕捉异常 d={} #例如定义字典 try: ...
- linux硬件资源问题排查:cpu负载、内存使用情况、磁盘空间、磁盘IO
在使用过程中之前正常的功能,突然无法使用,性能变慢,通常都是资源消耗问题,资源消耗可以从以下几个方面去排查.对于已经安装硬件资源监控软件(zabbix)的环境,直接使用硬件资源监控软件(zabbix) ...
- Redis 笔记(二)—— STRING 常用命令
字符串中不仅仅可以存储字符串,它可以存储以下 3 中类型的值 : 字符串 整数 浮点数 Redis 可以对字符串进行截取等相关操作,对整数.浮点数进行增减操作. 自增自减命令 命令 用例和描述 INC ...
- python--模块、列表生成式、集合元祖列表
一.导入模块的两种方式 1.直接使用import import 模块名 #调用 模块名.方法名() 2.使用from…import… from 模块名 import 方法名1,方法名2(from 模块 ...
- Linux下修改efi启动项
Linux下有一个efibootmgr工具可以编辑efi启动项,十分方便,简单介绍如下 直接运行efibootmgr会显示出当前所有efi启动项,每个启动项前都有相应编号, 可以使用efibootmg ...
- Golang源码分析之目录详解
开源项目「go home」聚焦Go语言技术栈与面试题,以协助Gopher登上更大的舞台,欢迎go home~ 导读 学习Go语言源码的第一步就是了解先了解它的目录结构,你对它的源码目录了解多少呢? 目 ...
- golang trace 分析 简例
今天,通过一个例子,一方面熟悉trace在自定义范围内的分析,另一方面golang 在协程调度策略上的浅析. Show Code // trace_example.go package main im ...