Elasticsearch 查询

By 刘志军 , 2019-12-14, 分类: elasticsearch

elasticsearch

ES的核心功能之一就是提供搜索,搜索有两种方式,一种从 url 中读取所有的查询参数,用 GET 请求。另一个是使用 POST 请求 将 JSON 数据作为请求体,支持完整的 Elasticsearch DSL。DSL查询表达式(Query DSL),它是一种非常灵活又富有表现力的 查询语言。 Elasticsearch 使用它可以以简单的 JSON 接口来展现 Lucene 功能的绝大部分。在你的应用中,你应该用它来编写你的查询语句。它可以使你的查询语句更灵活、更精确、易读和易调试。

例如:查询customer索引中任意字段中有关键字"深圳"的文档

GET /customer/_search?q=深圳

{
    "took": 3,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 1.7140323,
        "hits": [
            {
                "_index": "customer",
                "_type": "_doc",
                "_id": "1",
                "_score": 1.7140323,
                "_source": {
                    "name": "张真人",
                    "address": "广东深圳"
                }
            }
        ]
    }
}

你也可以用q=*来查询所有的结果 或者 _search 后面不带任何参数。

下面讨论的都是用 POST 请求 将 JSON 数据作为请求体的查询

单字段查询

用 match 指定单字段查询。

POST /customer/_search

# body
{
    "query" : {
         "match" : {"name":"张"}
    }
}

# 返回
{
    "took": 2,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 3,
            "relation": "eq"
        },
        "max_score": 0.27951443,
        "hits": [
            {
                "_index": "customer",
                "_type": "_doc",
                "_id": "1",
                "_score": 0.27951443,
                "_source": {
                    "name": "张真人",
                    "address": "广东深圳",
                    "age": 100
                }
            },
            {
                "_index": "customer",
                "_type": "_doc",
                "_id": "3",
                "_score": 0.27951443,
                "_source": {
                    "name": "张无忌",
                    "address": "万安寺",
                    "age": 20
                }
            },
            {
                "_index": "customer",
                "_type": "_doc",
                "_id": "0xMBGGoB15mDBRoAwkbg",
                "_score": 0.27951443,
                "_source": {
                    "name": "张翠山",
                    "address": "湖北十堰",
                    "age": 108
                }
            }
        ]
    }
}

分页

fromsize 指定返回数据的起始位置和数据的大小。

POST /customer/_search

# body
{ 
    "query" : {
         "match" : {"name":"张"}
    },
    "size":2,
    "from": 2
}
# 返回
{
    "took": 3,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 3,
            "relation": "eq"
        },
        "max_score": 0.27951443,
        "hits": [
            {
                "_index": "customer",
                "_type": "_doc",
                "_id": "0xMBGGoB15mDBRoAwkbg",
                "_score": 0.27951443,
                "_source": {
                    "name": "张翠山",
                    "address": "湖北十堰",
                    "age": 108
                }
            }
        ]
    }
}

指定返回字段

_source 用于指定返回的字段列表

POST /customer/_search
# body
{
    "query" : {
         "match" : {"name":"张"}
    },
    "_source": ["name"]
}

# 返回
{
    "took": 5,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 3,
            "relation": "eq"
        },
        "max_score": 0.27951443,
        "hits": [
            {
                "_index": "customer",
                "_type": "_doc",
                "_id": "0xMBGGoB15mDBRoAwkbg",
                "_score": 0.27951443,
                "_source": {
                    "name": "张翠山"
                }
            }
        ]
    }
}

高亮

POST /customer/_search
# body

{
    "query" : {
         "match" : {"name":"张"}
    },
    "highlight": {
        "fields" : {
            "name" : {}
        }
    }
}

# 返回

{
    "took": 80,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 3,
            "relation": "eq"
        },
        "max_score": 0.27951443,
        "hits": [
            {
                "_index": "customer",
                "_type": "_doc",
                "_id": "0xMBGGoB15mDBRoAwkbg",
                "_score": 0.27951443,
                "_source": {
                    "name": "张翠山"
                },
                "highlight": {
                    "name": [
                        "<em>张</em>翠山"
                    ]
                }
            }
        ]
    }
}

多索引查询

# 1、在URL中显示地指定索引
curl -XGET 'http://localhost:9200/index1,index2/_search?q=yourQueryHere'

# 2、所有索引中搜索
curl -XGET 'http://localhost:9200/_all/_search?q=yourQueryHere'

# 3、或者 
curl -XGET 'http://localhost:9200/_search?q=yourQueryHere'

多字段(Multi-filed)查询

用 multi_match 中的 fields 指定多字段,如果是所有字段中查询,则可以使用 [*] 代替

POST /_search

{
    "query" : {
         "multi_match" : {
          "query":    "张", 
          "fields": [ "name", "title" ] 
        }
    }
}

提升(Boosting)字段权重

当在多个字段中搜索关键字,但每个字段的权重不一样,例如标题和内容中都含有某个关键字,但是希望标题的权重更大一些时,可以用^提升字段权重,返回的数据如果是标题中有该关键字的就展示在前面。

{
    "query" : {
         "multi_match" : {
             "query":    "张", 
             "fields": [ "name^3", "address" ] 
         }
    }
}

Function Score Query

搜索结果默认会根据文档的相关度进行排序,在 Elasticsearch 中 function_score 是用于处理文档分值的 DSL,它会在查询结束后对每一个匹配的文档进行一系列的重新打分操作,以生成的最终分数进行排序。你可以在查询上指定一个或多个函数,它提供了几种默认的计算分值的函数。

函数计算得出的分值与原始的分值_score和并操作用属性boost_mode指定,boost_mode 有如下几种选项

field_value_factor:域值(Field Value)因子

把文档中的某个特定字段作为计算相关性分值的一个因素在很多场景可以使用,例如原创的文章分值更高,在搜索时,可以将 function_score 查询与 field_value_factor 结合使用。

这个例子中,我先将所有的为文档新增了age字段,我希望年龄大的排序更靠前。

{
    "query" : {
        "function_score": {
            "query": {
                "multi_match" : {
                    "query" : "张",
                    "fields": ["name"]
                }
            },
            "field_value_factor": {
                "field" : "age",
                "modifier": "log1p",
                "missing":0,
                "factor" : 2
            }
        }
    }
}

modifier 的值可以为: none (默认状态)、 log 、 log1p 、 log2p 、 ln 、 ln1p 、 ln2p 、 square 、 sqrt 以及 reciprocal。

factor 值大于 1 会提升效果, factor 值小于 1 会降低效果。

衰变(Decay)函数

有增长因子,也有衰变因子,比如时间,我希望越近越好,某个地址越近越好. decay functions 让我们可以基于一个单值的数值型字段(比如日期、地点或者价格类似标准的数值型字段)来计算分数。

这三个衰减函数分别为:

origin: 中心点或字段可能的最佳值,落在原点origin上的文档评分 _score 为满分1.0 比如如果你希望发布时间越近越好的话,那么当前是最好的。

scale: 衰减率,即一个文档从原点origin下落时,评分_score改变的速度(例如每 £10 欧元或每 100 米)。

decay: 从原点origin衰减到scale所得的评分_score,默认值为 0.5。

offset: 以原点origin为中心点,为其设置一个非零的偏移量offset 覆盖一个范围,而不只是单个原点。在范围 -offset <= origin <= +offset 内的所有评分_score都是 1.0。

例如:

POST /_search
{
    "query": {
        "function_score": {
            "query": {
                "multi_match" : {
                    "query" : "search engine",
                    "fields": ["title", "summary"]
                }
            },
            "functions": [
                {
                    "exp": {
                        "publish_date" : {
                            "origin": "2014-06-15",
                            "offset": "7d",
                            "scale" : "30d"
                        }
                    }
                }
            ],
            "boost_mode" : "replace"
        }
    },
    "_source": ["title", "summary", "publish_date", "num_reviews"]
}

布尔查询

布尔查询用于匹配复杂查询,例如搜索标题为“Python”的文章,同时要求阅读量大于1000,或者 发布时间必须在某个时间范围内。

POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user" : "kimchy" }
      },
      "filter": {
        "term" : { "tag" : "tech" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tag" : "wow" } },
        { "term" : { "tag" : "elasticsearch" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}

must 于 should 的区别是前者严格满足, 他们都可以接受单个字典,也可以接受多个字典组成的数组。

参考文档:


关注公众号「Python之禅」,回复「1024」免费获取Python资源

python之禅

猜你喜欢

2019-12-14
Elasticsearch基本操作
2019-12-14
Elasticsearch 分析器
2019-12-14
Elasticsearch 安装
2019-12-14
Elasticsearch基本概念
2019-12-14
Elasticsearch 映射