Elasticsearch(搜索(1)--基本的工具)

来源:互联网 发布:sql建立唯一索引 编辑:程序博客网 时间:2024/06/05 19:59

空搜索

最基本的搜索API表单是空搜索(empty search),它没有指定任何的查询条件,只返回集群中的索引文档:
请求命令:
url http://10.139.32.155:9200/_search
响应内容类似于这样:
{"took":18,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":20715,"max_score":1.0,"hits":[]}}

字段解释:
hits
响应中最重要的部分是hits,它包含了total字段来表示匹配到的文档总数,hits数组还包含了匹配到的前10条数据。

hits数组中的每个结果都包含_index、_type和文档的_id字段,被加入到_source字段中这意味着在搜索结果中我们将可以直接使用全部文档。这不像其它搜索引擎只返回文档ID,需要你单独去获取文档。

每个节点都有一个_score字段,这是相关性得分(relevance score),它衡量了文档与查询的匹配程度。默认的,返回的结果中关联性最大的文档排在首位;这意味着,它是按照_score降序排列的。这种情况下,我们没有指定任何查询,所以所有文档的相关性是一样的,因此所有结果的_score都是取得一个中间值1
max_score指的是所有文档匹配查询中_score的最大值。

took
took告诉我们整个搜索请求花费的毫秒数

shards
_shards 节点告诉我们参与查询的分片数(total字段),有多少是成功的(successful字段),有多少是失败的(failed字段)。通常我们不希望分片失败,不过这个有可能发生。如果我们遭受一些重大的故障导致主分片和复制分片都故障,那这个分片的数据将无法响应给搜索请求,这种情况下,Elasticsearch将报告分片failed,但仍将继续返回剩余的分片上的结果。

timeout
time_out 值告诉我们查询超时与否。一般的,搜索请求不会超时。如果响应速度比完整的结果更重要,你可以定义timeout参数为10或者10ms,或者1s
curl http://10.139.32.155:9200/_search?timeout=10
Elasticsearch将返回在请求超时前收集到的结果
超时不是一个短路器(circuit breaker)
警告:
timeout不会停止查询,它仅仅会告诉你目前顺利返结果的节点然后关闭连接。在后台,其他分片可能依旧执行查询,尽管结果已经被发送。
使用超时是因为对于你的业务需求来书非常重要,而不是你想中断执行长时间运行的结果。


多索引和多类别

通过限制搜索的不同索引或类型,我们可以在集群中跨所有文档搜索。Elasticsearch转发搜索请求到集群中平行的主分片或每个分片的复制分片上,收集结果后选择顶部十个返回给我们。
通常,你可能想搜索一个或多个自定义的索引或类型,我们能通过定义URl中的索引或类型达到这个目的,像这样:
/_search
在所有索引的所有类型中搜索

/joke/_search
在索引joke的所有类型中搜索

/joke,us/_search
在索引joke,us的所有类型中搜索

/j*,u*/_search
在以g或u开头的索引的所有类型中搜索

/joke/jt_joke/_search
在索引joke的类型jt_joke中搜索

/joke,us/jt_joke,cool_joke/_search
再索引joke,us的类型为jt_joke,cool_joke中搜索

/_all/jt_joke,cool_joke/_search
在所有的索引的类型为jt_joke,cool_joke中搜索

当你搜索包含单一索引时,Elasticsearch转发搜索请求到这个索引的主分片的复制分片上,然后聚集每个分片的结果。搜索包含多个索引也是同样的方式--只不过或有更多的分片被关联。

重要:
搜索一个索引有五个主分片和五个索引各有一个分片事实上一样。


分页

和SQL使用LIMIT关键字返回只有一页的结果一样,Elasticsearch接受from和size参数:
size:个数,默认10
from:跳过开始的结果数,默认为0
如果你想每页显示5个结果,页码从1到3,那请求如下:
curl http://10.139.32.155:9200/joke/_search?size=5
curl http://10.139.32.155:9200/joke/_search?size=5&from=5
应该当心分页太深或者一次请求太多的结果。结果在返回前会被排序。但是记住一个搜索请求常常涉及多个分片。每个分片生成自己排好序的结果,它们接着需要集中起来排序确保整体排序正确

简易搜索

search API有两种表单:一种是“简易版”的查询字符串(query string)将所有的参数通过查询字符串定义,另一种版本使用JSON完整的表示请求体(request body),这种富搜索语言叫做结构化查询语言(DSL)

查询字符串搜索对于命令行下运行点对点(ad hoc)查询特别有用。例如这个语句所有类型为jt_joke并在content字段中包含s字符的文档:
http://10.139.32.155:9200/_all/joke/_search?q=content:s

查找name字段包含“john”和tweet字段包含“mary”的结果。实际的查询只需要:
http://10.139.32.155:9200/_all/joke/_search?+name:john+tweet:mary

但是百分比编码(percent encoding)(url编码)需要将查询字符串参数变得更加神秘:
http://10.139.32.155:9200/_all/joke/_search?q=content:s+name%3Ajohn+tweet%3Amary

"+"前缀表示语句匹配条件必须满足。类似的"-"前缀表示条件必须不被满足。所有条件如果没有+或-表示是可选的-----------匹配越多,相关文档越多。


_all字段
返回包含“mary”字符的所文档的简单搜索:
curl -XGET "http:10.139.32.155:9200/_search?q=mary"
在前一个例子中,我们搜索tweet或name中包含某个字符的结果。然而,这个语句返回的结果在三个不同的字段中包含“mary”
.用户的名字是“Mary”
.“Mary”发的六个推文
.针对“@mary”的一个推文

Elasticsearch是如何找到三个不同字段的结果的?
当你索引一个文档,Elasticsearch把所有字符串字段值连接起来放在一个大字符串中,它被索引为一个特殊的字段_all。
好比我们增加了一个叫做_all的额外字段值:
查询字符串在其他字段被定义前使用_all字段搜索

更复杂的语句

下一个搜索推特的语句:
_all field
.name字段包含“mary或“john”
.date晚于2014-09-10
._all字段包含“aggregation”或“geo”

curl "http://10.139.32.155:9200/_search?q= +name:(mary john) +date:>2014-09-10 +(aggregation geo)"

编码后的查询字符串变得不太容易阅读:
curl "http://10.139.32.155:9200/_search?q=%2Bname%3A(mary john)+%2Bdate%3A>2014-09-10+%2B(aggregation geo)"

然而,你可以看到简洁带来了隐晦和调试困难。而且它很脆肉---查询字符串中一个细小的语法错误。
像-、:、/或"错位就会导致错误而不是结果
最后,查询字符串搜索允许任意用户在索引中任何一个字段上运行潜在的慢查询语句,可能暴露私有信息甚至使你的集群瘫痪。
因为这些原因,我们不建议直接暴露查询字符串搜索给用户,除非这些用户对于你的数据和集群可信。

取而代之的,生产环境我们一般依赖全功能的请求体搜索API,它能完成前面所有的事情,甚至更多。在了解它们之前,我们首先需要看看数据是如何在Elasticsearch中被索引的。

映射(mapping)机制用于进行字段类型确认,将每个字段匹配为一种确定的数据类型(string,number,booleans,date等)。

分析(analysis)机制用于进行全文文本(Full Text)的分词,以建立供搜索用的反向索引。

映射及分析

当在索引中处理数据时,我们注意到一些奇怪的事。有些东西似乎被破坏了:
在索引中有12个tweets,只有一个包含日期2014-09-15,但是我们看看下面语句中的total hits.

GET /_search?q=2014     #12个结果
GET /_search?q=2014-09-15  #还是12个结果
GET /_search?q=date:2014-09-15 #1个结果
GET /_search?q=date:2014 #0个结果
为什么全日期的查询返回所有的tweets,而针对date字段进行年度查询却什么都不返回?为什么我们的结果因_all字段或date字段而变得不同?

想必是因为我们的数据在_all字段的索引方式和字段在date字段的索引方式不同而导致的。
http://10.139.32.155:9201/joke/_mapping/jt_joke
返回:
{
    "joke": {
        "mappings": {
            "jt_joke": {
                "properties": {
                    "content": {
                        "type": "string",
                        "store": true
                    },
                    "name": {
                        "type": "string",
                        "store": true
                    }
                }
            }
        }
    }
}

Elasticsearch为对字段类型进行猜测,动态生成了字段和类型的映射关系。返回的信息显示date字段被识别为date类型。_all因为是默认字段所以没有在此显示,不过我们知道它是string类型。

date类型的字段和string类型的字段的索引方式是不同的,因此导致查询结果的不同,这并不会让我们觉得惊讶。

你会期望每一种核心数据类型(strings,numbers,booleans及dates)以不同的方式进行索引,而这点也是现实:在Elasticsearch中他们是被区别对待的。

但是更大的区别在于确切值(exact values)(比如strin类型)及全文文本(full text)之间。

这两者的区别才真的很重要-这是区分搜索引擎和其他数据库的根本差异。
















原创粉丝点击