Elasticsearch 文本和数字查询

这篇文章主要说一些es中的文本和数字的查询操作

使用term查询

搜索或过滤特定术语是非常频繁的。 trem查询使用精确的值匹配,通常非常快。term查询可以与MYSQL世界中相等的“=”查询进行比较(对于未tokenized的字段)。

curl -XPOST 'http://127.0.0.1:9200/test-index/test-type/_search?pretty=true' -d '
{
    "query": {
        "term": {
            "uuid": "33333"
        }
    }
}'

为了把term查询弄成filter,我们需要使用bool查询进行包装:

curl -XPOST 'http://127.0.0.1:9200/test-index/test-type/_search?pretty=true' -d '
{
    "query": {
        "bool": {
            "filter": {
                "term": {
                    "uuid": "33333"
                }
            }
        }
    }
}'

一个建议就是,如果你并不是关心文档的score,那么就应该总是使用term filter。因为使用filtel,不需要计算score,少一些计算量,而且结果也可以缓存
在filter query中,filter首先应用,将要匹配的文档数量缩小到查询中,然后应用query。
term匹配是es中非常重要的一个基本概念,为了正确的使用term查询,需要关注被查询的字段是否tokenized:

  • KeywordAnalyzer 对于not tokenized字段默认使用。
  • StandardAnalyzer 对于type=’text’字段默认使用,比如Peter's house is big的tokenized之后的内容为:["peter", "s", "house", "is", "big"]

使用terms查询

如果你想一次查询多个term,可以使用bool查询或者terms查询。很像mysql中的in一样。

curl -XPOST 'http://127.0.0.1:9200/test-index/test-type/_search?pretty=true' -d '
{
    "query": {
        "terms": {
            "uuid": [
                "33333",
                "32222"
            ]
        }
    }
}'

terms查询允许您定义额外的参数来控制查询行为,如:

  • minimum_match/minimum_should_match 这样可以控制需要多少匹配的条件来验证查询,如下所示:
    "terms": {
        "color": [
            "red",
            "blue",
            "white"
        ],
        "minimum_should_match": 2
    }
    

这个查询匹配所有文档,其中颜色字段至少有两个值在红色,蓝色和白色之间,也就是至少包含上面3个颜色中的2个。

  • boost:这是用于修改查询权重的标准查询boost值。 如果您希望对匹配的条款提供更多的相关性,以增加最终的文档分数,这可能非常有用。

terms query非常强大,在查询期间可以通过其他文档获取这些term,比如在MySQL中select * from xxx where can_see_group in (select groups from user where user_id='1bw71LaxSzSp_zV6NB_YGg'),等价的在terms query中的写法为:

curl -XGET localhost:9200/my-index/document/_search?pretty=true -d '
{
    "query": {
        "terms": {
            "can_see_groups": {
                "index": "my-index",
                "type": "user",
                "id": "1bw71LaxSzSp_zV6NB_YGg",
                "path": "groups"
            }
        }
    }
}'

es并没有提供类似于SQL join那样的操作,但是提供了一些替代物:

  • Child/parent queries
  • Nested queries
  • Terms filtered with external document term fetching.

前缀查询

前缀查询很像MYSQL的select * from xxx where a like 'prefix%'这种:

curl -XPOST 'http://127.0.0.1:9200/test-index/test-type/_search?pretty=true' -d '
{
    "query": {
        "prefix": {
            "uuid": "222"
        }
    }
}'

当您搜索结尾文本时,前缀查询可以非常方便。
例如,用户必须将文档与具有结尾扩展名png的字段filename匹配。 通常,用户倾向于执行类似于*.png。但是正则表达式需要检查字段的每个字段,因此计算时间非常长。最佳做法是使用反向分析器对文件名字段进行索引,做法如下:

  • 在索引级别定义一个reverse_analyzer:
    {
        "settings": {
            "analysis": {
                "analyzer": {
                    "reverse_analyzer": {
                        "type": "custom",
                        "tokenizer": "keyword",
                        "filter": [
                            "lowercase",
                            "reverse"
                        ]
                    }
                }
            }
        }
    }
    

  • 当我们定义filename字段的时候,我们使用上面定义的reverse_analyzer:

    "filename" : { "type" : "keyword", "fields":{ "rev":{ "type" : "text", "analyzer": "reverse_analyzer" } } },

  • 现在我们就可以使用前缀查询了:

    "query": {"prefix": { "filename.rev": ".png"} }

因为文本分析器既用于索引,也用于搜索前缀文本,当查询执行时,.png将自动被处理为gnp.。
这样,当我们索引文件名为a.png的时候,存储的filename内容就是:a.png, filename.rev就是gnp.a

通配符查询

curl -XPOST 'http://127.0.0.1:9200/test-index/test-type/_search?pretty=true' -d '
{
    "query": {
        "wildcard": {
            "uuid": "22?2*"
        }
    }
}'
  • * 0个或者多个字符
  • ? 1个字符

在查询执行期间,搜索字段的所有条款都与通配符查询进行匹配。 因此,通配符查询的性能取决于您的条款的基数。 为了提高性能,建议不要执行以*或?开头的通配符查询。

使用正则表达式查询

curl -XPOST 'http://127.0.0.1:9200/test-index/test-type/_search?pretty=true' -d '
{
    "query": {
        "regexp": {
            "parsedtext": {
                "value": "j.*",
                "flags": "INTERSECTION|COMPLEMENT|EMPTY"
            }
        }
    }
}'

匹配正则表达式结果的文档的score永远是1.0。也有一些参数:

  • boost 默认是1.0,这包括用于提升此查询的分数的值。
  • flags 下面这些标签使用|分割
    • ALL 这将启用所有可选的regexp语法
    • ANYSTRING This enables anystring (@)
    • AUTOMATON This enables named automata ()
    • COMPLEMENT This enables complement (~)
    • EMPTY This enables empty language (#)
    • INTERSECTION This enables intersection (&)
    • INTERVAL This enables numerical intervals ()
    • NONE This enables no optional regexp syntax

span查询

这个说实话我没用过,看了一下官方文档,感觉实际工作中好像不太常用,所以先略过
https://www.elastic.co/guide/en/elasticsearch/reference/current/span-queries.html

match query

用于执行全文查询的标准查询,包括模糊匹配和短语或邻近查询。

curl -XGET 'localhost:9200/_search?pretty' -H 'Content-Type: application/json' -d'
{
    "query": {
        "match" : {
            "message" : "this is a test"
        }
    }
}'

其中message是字段名
如果你先执行相同的查询,但是作为phrase query执行,那么修改为:

curl -XGET 'localhost:9200/_search?pretty' -H 'Content-Type: application/json' -d'
{
    "query": {
        "match_phrase" : {
            "message" : "this is a test"
        }
    }
}'

match query 的类型为boolean。 这意味着分析所提供的文本,并且分析过程从提供的文本构造一个布尔查询。operator参数可以设置为or或者and, 默认是or
可以使用minimum_should_match参数设置要匹配的可选should子句的最小数量。

curl -XGET 'localhost:9200/_search?pretty' -H 'Content-Type: application/json' -d'
{
    "query": {
        "match" : {
            "message" : {
                "query" : "this is a test",
                "operator" : "and"
            }
        }
    }
}'

一个比较常见的场景就是使用相同的查询查询多个字段,那么久可以使用multi_match:

curl -XPOST 'http://127.0.0.1:9200/test-index/test-type/_search?pretty=true' -d '
{
    "query": {
        "multi_match": {
            "fields": [
                "parsedtext",
                "name"
            ],
            "query": "Bill",
            "operator": "and"
        }
    }
}'

query string query

查询字符串查询是一种特殊类型的查询,允许通过混合字段规则来定义复杂查询。
比如我们想要搜索一个文本nice guy, 但是想丢弃term not,并且展示价格小于5的,那么我们的查询可以是:

curl -XPOST 'http://127.0.0.1:9200/test-index/test-type/_search?pretty=true' -d '
{
    "query": {
        "query_string": {
            "query": "nice guy -parsedtext:not price:{ * TO 5} ",
            "fields": [
                "parsedtext^5"
            ],
            "default_operator": "and"
        }
    }
}'

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html

range query

curl -XPOST 'http://127.0.0.1:9200/test-index/test-type/_search?pretty=true' -d '
{
    "query": {
        "range": {
            "position": {
                "from": 3,
                "to": 4,
                "include_lower": true,
                "include_upper": false
            }
        }
    }
}'

如果字段是date类型,那么会自动转为数字处理的:

"range" : { "timestamp" : { "from" : "2014-01-01", "to" : "2015-01-01", "include_lower" : true, "include_upper" : false} }

IDs query

curl -XPOST 'http://127.0.0.1:9200/test-index/test-type/_search?pretty=true' -d '
{
    "query": {
        "ids": {
            "type": "test-type",
            "values": [
                "1",
                "2",
                "3"
            ]
        }
    }
}'

exists query

一般用来检查某个字段是否存在

curl -XPOST 'http://127.0.0.1:9200/test-index/test-type/_search?pretty=true' -d '
{
    "query": {
        "exists": {
            "field": "parsedtext"
        }
    }
}'
本文版权归作者所有,禁止一切形式的转载,复制等操作
赞赏

微信赞赏支付宝赞赏

发表评论

电子邮件地址不会被公开。 必填项已用*标注