现在我们可以开始探讨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. 1.3 正则表达式和Python语言-1.3.5使用 search()在一个字符串中查找模式(搜索与匹配 的对比)

    1.3.5 使用 search()在一个字符串中查找模式(搜索与匹配的对比) 其实,想要搜索的模式出现在一个字符串中间部分的概率,远大于出现在字符串起始部分的概率.这也就是 search()派上用场的 ...

  2. Comparing randomized search and grid search for hyperparameter estimation

    Comparing randomized search and grid search for hyperparameter estimation Compare randomized search ...

  3. 【起航计划 032】2015 起航计划 Android APIDemo的魔鬼步伐 31 App->Search->Invoke Search 搜索功能 Search Dialog SearchView SearchRecentSuggestions

    Search (搜索)是Android平台的一个核心功能之一,用户可以在手机搜索在线的或是本地的信息.Android平台为所有需要提供搜索或是查询功能的应用提 供了一个统一的Search Framew ...

  4. search(8)- elastic4s-search-query模式

    上篇提过query模式除对记录的筛选之外还对符合条件的记录进行了评分,即与条件的相似匹配程度.我们把评分放在后面的博文中讨论,这篇我们只介绍query查询. 查询可以分为绝对值查询和全文查询:绝对值查 ...

  5. [Math] Beating the binary search algorithm – interpolation search, galloping search

    From: http://blog.jobbole.com/73517/ 二分检索是查找有序数组最简单然而最有效的算法之一.现在的问题是,更复杂的算法能不能做的更好?我们先看一下其他方法. 有些情况下 ...

  6. 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 ...

  7. 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导致的溢 ...

  8. Depth-first search and Breadth-first search 深度优先搜索和广度优先搜索

    Depth-first search Depth-first search (DFS) is an algorithm for traversing or searching tree or grap ...

  9. [Algorithm] Beating the Binary Search algorithm – Interpolation Search, Galloping Search

    From: http://blog.jobbole.com/73517/ 二分检索是查找有序数组最简单然而最有效的算法之一.现在的问题是,更复杂的算法能不能做的更好?我们先看一下其他方法. 有些情况下 ...

随机推荐

  1. zookeeper java代码实现master 选举

    1,master选举使用场景及结构 现在很多时候我们的服务需要7*24小时工作,假如一台机器挂了,我们希望能有其它机器顶替它继续工作.此类问题现在多采用master-salve模式,也就是常说的主从模 ...

  2. js的预编译

    JavaScript不会完全按照代码的顺序执行,在执行之前会对定义的函数和变量先来一边所谓的预编译处理. 先来说下对变量的预处理: console.log(a) //undefined var a = ...

  3. Unable to locate JAR/zip in file system as specified by the driver definitio

    把之前的驱动包删掉,然后把你的驱动包导入就行了 现在OK键就算正常了

  4. 《java编程思想》一切都是对象

    1. 用引用操纵对象 在Java中一切皆对象,我们平常在对java中的类进行操作时,其实操作的不是对象本身而是对象的引用.我们可以将这想象成用遥控器(引用)操作电视机(对象),只要握住这个遥控器,就能 ...

  5. Android 数据库框架 DBFlow 的使用

    原文首发于微信公众号:jzman-blog,欢迎关注交流! DBFlow 是一个基于注解处理器开发的使用方便的 ORM Android 数据库,该库简化了很多多余的代码,并且提供了好用的 API 来处 ...

  6. Axure RP闪退问题

    Axure RP 在mac 环境,当时安装的是8.好久没用了,最近打开,一开就闪退. 网上找了一下,显示的都是各种文件夹没权限的问题,实验了一下不管用. /Applications/develop/A ...

  7. HTML特殊转义字符——特殊符号

    干货,见下图: 后期我会陆续更一些JavaScript的文章,大家可以一起学习交流.

  8. E 比赛评分

    时间限制 : - MS   空间限制 : - KB  评测说明 : 1s,128m 问题描述 Lj​最近参加一个选秀比赛,有N个评委参加了这次评分,N是奇数.评委编号为1到N.每位评委给Lj​的分数是 ...

  9. html5 css写出一个实心三角形和空心三角行

    原理:css中的border属性的特殊性. 实心三角形: html5: <div id="mydiv"></div> css: #mydiv{ height ...

  10. MariaDB使用数据库查询《三》

                                                                 MariaDB使用数据库查询 案例5:使用数据库查询 5.1 问题 本例要求配 ...