【ES】学习4-结构化搜索

1. 结构化搜索得到的结果只有,没有相似概念。

 

term可以实现精确值查询

curl -XGET 'localhost:9200/logstash-cowrie/_search?pretty' -d '
{"query":
    { "constant_score":{
        "filter":{
            "term": {"src_ip": "192.168.188.88"}
            }
        }
    }
}'

因为term是非评分的,所以要用constant_score的方式将其转化为过滤器。注意:如果没有constant_score是会报错的。

 

查看字段是否可以用精确值查询,可以通过analyze API。下面是例子,可以看到ip只有一个token可以精确查询。

curl -XGET 'localhost:9200/test/_analyze?pretty' -d '{"field":"src_ip","text": "192.168.188.88"}'
#结果
{
  "tokens" : [
    {
      "token" : "192.168.188.88",
      "start_offset" : 0,
      "end_offset" : 14,
      "type" : "<NUM>",
      "position" : 0
    }
  ]
}

 

设置字段具有精确值,如果想修改已有字段只能删除后重新建立。例子:

DELETE /my_store 

PUT /my_store 
{
    "mappings" : {
        "products" : {
            "properties" : {
                "productID" : {
                    "type" : "string",
                    "index" : "not_analyzed" 
                }
            }
        }
    }

}

 

 

组合过滤:

{
   "bool" : {
      "must" :     [],   #与
      "should" :   [],   #或
      "must_not" : [],  #非
   }
}

例子1:

curl -XGET 'localhost:9200/test/_search?pretty' -d '
{"query":
    {"constant_score":{
        "filter":{
            "bool":{
                "should":[{"term": {"src_ip": "192.168.188.88"}},{"term": {"src_ip": "1.2.3.4"}}],
                "must":{"range":{"timestamp":{"gte":"2016-10-24T00:00:00", "lt":"2017-10-25T00:00:00"}}}
                }
            }
        }
    }
}'

注意单个条件和多个条件的写法。

单个条件,直接用 {}

多个条件,用 [{},{}]

注意:https://elasticsearch.cn/book/elasticsearch_definitive_guide_2.x/combining-filters.html中的例子中用了filtered关键字,该关键字在新版es中已经被废除了。

 

bool表达式的嵌套

src_ip=192.168.188.88 or (src_ip=1.2.3.4 and 2016-10-24<=time<2017-10-25)

curl -XGET 'localhost:9200/test/_search?pretty' -d '
{"query":
    {"constant_score":{
        "filter":{
            "bool":{
                "should":[
                   {"term": {"src_ip": "192.168.188.88"}},
                   {"bool":{
                        "must": 
                            [{"term":{"src_ip": "1.2.3.4"}},
                            {"range":{"timestamp":{"gte":"2016-10-24T00:00:00", "lt":"2017-10-25T00:00:00"}}}]
                        }
                    }]
                }
            }
        }
    }
}'

 

查找多个精确值 terms

{
  "terms": {   "src_ip": ["1.2.3.4","5.6.7.8"] } }

注意,term和terms表示包含,而不是相等

{ "term" : { "tags" : "search" } } 可以匹配下面两个文档

{ "tags" : ["search"] }
{ "tags" : ["search", "open_source"] }

如果想要完全一样,必须用其他字段增加约束。

 

范围range

"range" : {
    "price" : {
        "gte" : 20,
        "lte" : 40
    }
}

日期范围可以在日期上做运算

"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-01 00:00:00||+1M" 
    }
}
"range" : {
    "timestamp" : {
        "gt" : "now-1h"
    }
}

字符串范围:(不推荐,会很慢)

range 查询同样可以处理字符串字段, 字符串范围可采用 字典顺序(lexicographically) 或字母顺序(alphabetically)。

  • 5, 50, 6, B, C, a, ab, abb, abc, b  字典范围排序
"range" : {
    "title" : {
        "gte" : "a",
        "lt" :  "b"
    }
}

数字和日期字段的索引方式使高效地范围计算成为可能。 但字符串却并非如此,要想对其使用范围过滤,Elasticsearch 实际上是在为范围内的每个词项都执行 term 过滤器,这会比日期或数字的范围过滤慢许多。

字符串范围在过滤 低基数(low cardinality) 字段(即只有少量唯一词项)时可以正常工作,但是唯一词项越多,字符串范围的计算会越慢。

 

存在查询:exists

GET /my_index/posts/_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "exists" : { "field" : "tags" }
            }
        }
    }
}

 

缺失查询:missing

GET /my_index/posts/_search
{
    "query" : {
        "constant_score" : {
            "filter": {
                "missing" : { "field" : "tags" }
            }
        }
    }
}

 

注意下面这个例子

{
   "name" : {
      "first" : "John",
      "last" :  "Smith"
   }
}

查询

{
    "exists" : { "field" : "name" }
}

实际执行的是

{
    "bool": {
        "should": [
            { "exists": { "field": "name.first" }},
            { "exists": { "field": "name.last" }}
        ]
    }
}

这也就意味着,如果 first 和 last 都是空,那么 name 这个命名空间才会被认为不存在。

 

posted @ 2017-06-06 18:07  匡子语  阅读(286)  评论(0编辑  收藏  举报