一、面向文档
二、Json
三、索引
四、检索文档
1、简单搜索
2、搜索全部商品信息
3、query string
4、用DSL语句查询
5、全文搜索
6、短语搜索
7、高亮搜索(highlight)
8、聚合
一、面向文档
1、假如们在数据库中有一张商品表,当我想通过一个商品名称去模糊匹配的时候,那么的的sql可能是这样的
select a.* from product a where a.productName like %xxx%
那假如我还有一张表商品的型号表(一个商品有多个型号也就是1对多的关系)
我就必须使用left join 然后将商品型号表作为一个list放入到对应的商品下面,组成json数据类似于这样
{
"productName": "商品名称",
"productCode": "商品编号",
"model": [
{
"name": "型号1"
},
{
"name": "型号2"
}
]
}
我们知道商品表和商品型号表都是一行和列的数据结构存储在数据库中的,因此,每次进行查询的时候都必须进行sql查询和json数据的拼装等工作。
如果使用Elasticsearch就不必如此。
Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。这种理解数据的方式与以往完全不同,这也是Elasticsearch能够执行复杂的全文搜索的原因之一。
二、Json
ELasticsearch使用JSON,作为文档序列化格式。
三、索引
还是以上面的商品为例,我有这样一个需求
1、检索任何商品的所有信息。
2、支持结构化搜索,例如查找价格为20元以上的商品。
3、支持简单的全文搜索和更复杂的短语搜索
4、高亮搜索结果中的关键字
5、能够利用图表管理分析这些数据
每个文档代表一个商品,在考虑这些之前我们应该要知道数据要存在什么地方
在Elasticsearch中,文档归属于一种类型(type),而这些类型存在于索引(index:它是相关文档存储的地方)中,我们可以画一些简单的对比图来类比传统关系型数据库:
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
Elasticsearch集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型(types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)
默认情况下,文档中的所有字段都会被索引(拥有一个倒排索引),只有这样他们才是可被搜索的。
现在我创建一个文档
每个文档的类型为product
PUT /mytest/product/1
{
"productName": "商品名称",
"productCode": "商品编号",
"model": [
{
"name": "型号1"
},
{
"name": "型号2"
}
]
}
我们可以加多几个文档,方便到时候进行搜索
PUT /mytest/product/2
{
"productName": "商品名称2",
"productCode": "商品编号2",
"model": [
{
"name": "型号4"
},
{
"name": "型号5"
}
]
}
PUT /mytest/product/3
{
"productName": "商品名称3",
"productCode": "商品编号3",
"model": [
{
"name": "型号6"
},
{
"name": "型号7"
}
]
}
四、检索文档
1、简单搜索
mytest/product/1
2、搜索全部商品信息
mytest/product/_search
我们在结尾使用关键字_search来取代原来的文档ID。响应内容的hits数组中包含了我们所有的三个文档。默认情况下搜索会返回前10个结果
3、query string:搜索姓氏中包含“2”的商品 这种方法常被称作查询字符串(query string)搜索,请求中依旧使用_search关键字然后加上"?q=",比如:/mytest/product/_search?q=productName:2
4、 使用DSL语句查询:Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。
GET /mytest/product/_search
{
"query" : {
"match" : {
"productName" : "2"
}
}}
5、全文搜索
GET /mytest/product/_search
{
"query" : {
"match" : {
"productName" : "商品3"
}
}}
默认情况下,Elasticsearch根据结果相关性评分来对结果集进行排序,所谓的「结果相关性评分」就是文档与查询条件的匹配程度。很显然,排名第一的‘商品名称3‘’的productName字段明确的写到“商品3”。
但是为什么‘商品名称2’和'商品名称'也会出现在结果里呢?原因是“商品”在她的productName字段中被提及了。因为只有“商品”被提及而“3”没有,所以她的_score要低于‘商品名称3’。
这个例子很好的解释了Elasticsearch如何在各种文本字段中进行全文搜索,并且返回相关性最大的结果集。相关性(relevance)的概念在Elasticsearch中非常重要,而这个概念在传统关系型数据库中是不可想象的,因为传统数据库对记录的查询只有匹配或者不匹配。
6、短语搜索
有时候我们想确切的匹配若干个单词或者短语(phrases) ,那就使用match_phrase
GET /mytest/product/_search
{
"query" : {
"match_phrase" : {
"productName" : "商品名称3"
}
}}
上面的查询将只返回‘商品名称3’这个一个文档
7、高亮搜索(highlight)
GET /mytest/product/_search
{
"query" : {
"match_phrase" : {
"productName" : "名称3"
}
}
,
"highlight": {
"fields" : {
"productName" : {}
}
}}
当我们运行这个语句时,会命中与之前相同的结果,但是在返回结果中会有一个新的部分叫做highlight,这里包含了来自about字段中的文本,并且用来标识匹配到的单词。
8、聚合
Elasticsearch有一个功能叫做聚合(aggregations),它允许你在数据上生成复杂的分析统计。它很像SQL中的GROUP BY但是功能更强大。
首先在5.X后直接使用下面代码进行聚合操作时提示“Fielddata is disabled on text fields by default。。。”的错误
GET /mytest/product/_search
{
"aggs" : {
"all_productName" : {
"terms" : { "field" : "productName" }
}
}
}
具体解决方法在 这里(原因:聚合这些操作用单独的数据结构(fielddata)缓存到内存里了,需要单独开启)。所以在5.X以后需要加上
PUT mytest/_mapping/product
{
"properties": {
"productName": {
"type": "text",
"fielddata": true
}
}
}
聚合也允许分级汇总比如,统计上述结果中商品的平均价格,那么首先我先加入价格字段 "price"
那么我查询的所有数据就带上了价格字段
类似这样
{"took":0,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":3,"max_score":1.0,"hits":[{"_index":"mytest","_type":"product","_id":"2","_score":1.0,"_source":{
"productName": "商品名称2",
"productCode": "商品编号2",
"price": 200,
"model": [
{
"name": "型号1"
},
{
"name": "型号2"
}
]
}
},{"_index":"mytest","_type":"product","_id":"1","_score":1.0,"_source":{
"productName": "商品名称1",
"productCode": "商品编号1",
"price": 100,
"model": [
{
"name": "型号1"
},
{
"name": "型号2"
}
]
}
},{"_index":"mytest","_type":"product","_id":"3","_score":1.0,"_source":{
"productName": "商品名称3",
"productCode": "商品编号3",
"price": 300,
"model": [
{
"name": "型号1"
},
{
"name": "型号2"
}
]
}
}]}}
查询平均价格
GET /mytest/product/_search
{
"aggs" : {
"all_productName" : {
"terms" : { "field" : "productName" },
"aggs" : {
"avg_price" : {
"avg" : { "field" : "price" }
}
}
}
}
}