【ElasticSearch入门】8、基于词项和全文的分析,结构化搜索
一、基于term查询
- Term Level Query:Term Query / Range Query / Exists Query / Prefix Query / Wildcard Query
- 在 ES 中,Term 查询,对输入不做分词。会将输入作为一个整体,在倒排索引中查找准确的词项,并且使用相关度算分公式为每个包含该词项的文档进行相关度算分 - 例如 “Apple Store”
- 可以通过 Constant Score 将查询转换换成一个 Filtering,避免算分,并利用缓存,提交性能
demo
DELETE products
PUT products
{
"settings": {
"number_of_shards": 1
}
}
//创建索引,插入数据
POST /products/_bulk
{ "index": { "_id": 1 }}
{ "productID" : "XHDK-A-1293-#fJ3","desc":"iPhone" }
{ "index": { "_id": 2 }}
{ "productID" : "KDKE-B-9947-#kL5","desc":"iPad" }
{ "index": { "_id": 3 }}
{ "productID" : "JODL-X-1937-#pV7","desc":"MBP" }
//查询iPhone
POST /products/_search
{
"query": {
"term": {
"desc": {
"value": "iPhone"
}
}
}
}
没有相关匹配项,原因:因为在插入相关数据时,es分词过程中讲大写字母改为了小写。而term为精准查询,所以没有结果。
将iphone改为小写即产生结果。
或者将其改为keyword查询,也可以将大写iPhone查出来。
POST /products/_search
{
"query": {
"term": {
"desc.keyword": {
"value": "iPhone"
}
}
}
}
term查询会返回算分结果的。
- 将 Query 转成 Filter,忽略 TF-IDF 计算,避免相关性算分的开销
- Filter 可以有效利用缓存
POST /products/_search
{
"explain": true,
"query": {
"constant_score": {
"filter": {
"term": {
"productID.keyword": "XHDK-A-1293-#fJ3"
}
}
}
}
}
二、基于全文本的查询
基于全文本的查找
- Match Query / Match Phrase Query / Query String Query
特点
- 索引和搜索时会进行分词,查询字符串先传递到一个合适的分词器,然后生成一个供查询的词项列表
- 查询时候,先会对输入的查询进行分词。然后每个词项逐个进行底层的查询,最终将结果进行合并。并未每个文档生成一个算分。 例如查 “Martix reloaded”, 会查到包括 Matrix 或者 reload 的所有结果。
demo
PUT groups
{
"mappings": {
"properties": {
"names":{
"type": "text",
"position_increment_gap": 100 //数组之间每项的gap距离
}
}
}
}
GET groups/_mapping
POST groups/_doc
{
"names": [ "John Water", "Water Smith"]
}
POST groups/_search
{
"query": {
"match_phrase": {
"names": {
"query": "Water Water",
"slop": 0
}
}
}
}
由于每项之间gap的距离为100,而查询时指定slop为0,无法匹配两个water,查询结果为空。
若将slop改为100,则结果如下所示。
全部查出。
三、结构化的搜索
结构化数据
结构化搜索(Structured search) 是指对结构化数据的搜索
- 日期,布尔类型和数字都是结构化
文本也可以是结构化的
- 如彩色笔可以有离散的颜色集合:红(red)、绿(green)、蓝(blue)
- 一个博客可能被标记了标签,例如,分布式(distributed)和搜索(search)
- 电商网站上的商品都有 UPCs(通用产品码 Universal Product Codes)或其他的唯一标识,它们都遵从严格规定的、结构化的格式
demo
#结构化搜索,精确匹配
DELETE products
POST /products/_bulk
{ "index": { "_id": 1 }}
{ "price" : 10,"avaliable":true,"date":"2018-01-01", "productID" : "XHDK-A-1293-#fJ3" }
{ "index": { "_id": 2 }}
{ "price" : 20,"avaliable":true,"date":"2019-01-01", "productID" : "KDKE-B-9947-#kL5" }
{ "index": { "_id": 3 }}
{ "price" : 30,"avaliable":true, "productID" : "JODL-X-1937-#pV7" }
{ "index": { "_id": 4 }}
{ "price" : 30,"avaliable":false, "productID" : "QQPX-R-3956-#aD8" }
GET products/_mapping
插入部分数据
POST products/_search
{
"profile": true,
"explain": true,
"query": {
"term": {
"avaliable": {
"value": "true"
}
}
}
}
查询Boolean值
改为constant score+filter型式,减少算分消耗。
POST products/_search
{
"profile": true,
"explain": true,
"query": {
"constant_score": {
"filter": {
"term": {
"avaliable": "true"
}
}
}
}
}
terms数字查询:
POST products/_search
{
"profile": true,
"explain": true,
"query": {
"constant_score": {
"filter": {
"terms": {
"price": ["20","30"] //返回price 20 or 30的doc
}
}
}
}
}
数字范围查询:
POST products/_search
{
"profile": true,
"explain": true,
"query": {
"constant_score": {
"filter": {
"range": {
"price": {
"gte":20, //返回大于等于 20 小于等于 30的doc
"lte": 30
}
}
}
}
}
}
日期型:
POST products/_search
{
"profile": true,
"explain": true,
"query": {
"constant_score": {
"filter": {
"range": {
"date": {
"gte":"now-4y" //返回大于当前时间四年前的doc
}
}
}
}
}
}
exists 查询 - 非空查询
处理多值字段
插入数据
#处理多值字段
POST /movies/_bulk
{ "index": { "_id": 1 }}
{ "title" : "Father of the Bridge Part II","year":1995, "genre":"Comedy"}
{ "index": { "_id": 2 }}
{ "title" : "Dave","year":1993,"genre":["Comedy","Romance"] }
#处理多值字段,term 查询是包含,而不是等于
POST movies/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"genre.keyword": "Comedy" //返回所有genre包含comedy的doc
}
}
}
}
}
若想返回只有comedy gennre的doc,可以增加一个字段,控制genre数量。
插入doc
POST /movies/_bulk
{ "index": { "_id": 3 }}
{ "title" : "Father of the Bridge Part II","year":1995, "genre":"Comedy","genre_count" : 1}
{ "index": { "_id": 4 }}
{ "title" : "Dave","year":1993,"genre":["Comedy","Romance"],"genre_count" : 2 }
查询
POST movies/_search
{
"query": {
"constant_score": {
"filter": {
"bool": {
"must":[
{ "term" : { "genre.keyword" : "Comedy" }}, //只返回comedy类型的doc
{ "term" : { "genre_count" : 1 } }
]
}
}
}
}
}