结构化搜索
结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程
在结构化查询中,我们得到的结果 总是 非是即否,要么存于集合之中,要么存在集合之外。
结构化查询不关心文件的相关度或评分;它简单的对文档包括或排除处理。
精确值查找
当进行精确值查找时, 我们会使用过滤器(filters)。
term 查询 数字
我们首先来看最为常用的 term 查询, 可以用它处理数字(numbers)、布尔值(Booleans)、日期(dates)以及文本(text)。
- 让我们以下面的例子开始介绍,创建并索引一些表示产品的文档,文档里有字段
price
和productID
(价格
和产品ID
):
POST /my_store/products/_bulk
{ "index": { "_id": 1 }}
{ "price" : 10, "productID" : "XHDK-A-1293-#fJ3" }
{ "index": { "_id": 2 }}
{ "price" : 20, "productID" : "KDKE-B-9947-#kL5" }
{ "index": { "_id": 3 }}
{ "price" : 30, "productID" : "JODL-X-1937-#pV7" }
{ "index": { "_id": 4 }}
{ "price" : 30, "productID" : "QQPX-R-3956-#aD8" }
sql:查找具有某个价格的所有产品
SELECT document FROM products WHERE price = 20
DSL:
GET /my_store/products/_search
{
"query": {"term": {
"price": {
"value": "20"
}
}}
}
GET /my_store/products/_search
{
"query": {
"term": {
"price": "20"
}}
}
通常当查找一个精确值的时候,我们不希望对查询进行评分计算。只希望对文档进行包括或排除的计算,所以我们会使用 constant_score 查询以非评分模式来执行 term 查询并以一作为统一评分
GET /my_store/products/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"price": "20"
}
},
"boost": 1.2
}
}
}
term 查询 文本
sql:
SELECT product FROM products WHERE productID = "XHDK-A-1293-#fJ3"
DSL:
GET /my_store/products/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"productID": "XHDK-A-1293-#fJ3"
}
},
"boost": 1.2
}
}
}
但这里有个小问题:我们无法获得期望的结果。为什么呢?问题不在 term 查询,而在于索引数据的方式,
如果我们使用 analyze API (分析 API),我们可以看到这里的 UPC 码被拆分成多个更小的 token.
GET /my_store/_analyze
{
"field": "productID",
"text": "XHDK-A-1293-#fJ3"
}
{
"tokens" : [ {
"token" : "xhdk",
"start_offset" : 0,
"end_offset" : 4,
"type" : "<ALPHANUM>",
"position" : 1
}, {
"token" : "a",
"start_offset" : 5,
"end_offset" : 6,
"type" : "<ALPHANUM>",
"position" : 2
}, {
"token" : "1293",
"start_offset" : 7,
"end_offset" : 11,
"type" : "<NUM>",
"position" : 3
}, {
"token" : "fj3",
"start_offset" : 13,
"end_offset" : 16,
"type" : "<ALPHANUM>",
"position" : 4
} ]
}
这里有几点需要注意:
- Elasticsearch 用 4 个不同的 token 而不是单个 token 来表示这个 UPC 。
- 所有字母都是小写的。
- 丢失了连字符和哈希符( # )
所以当我们用 term 查询查找精确值 XHDK-A-1293-#fJ3 的时候,找不到任何文档,因为它并不在我们的倒排索引中,正如前面呈现出的分析结果,索引里有四个 token 。
为了避免这种问题,我们需要告诉 Elasticsearch 该字段具有精确值,要将其设置成 not_analyzed 无需分析的
DELETE /my_store
PUT /my_store
{
"mappings": {
"products":{
"properties": {
"productID":{
"type": "keyword"
}
}
}
}
}
GET /my_store/products/_search
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"productID" : "XHDK-A-1293-#fJ3"
}
}
}
}
}
组合过滤器
SQL:
SELECT product
FROM products
WHERE (price = 20 OR productID = "XHDK-A-1293-#fJ3")
AND (price != 30)
DSL:
- must
所有的语句都 必须(must) 匹配,与 AND 等价。 - must_not
所有的语句都 不能(must not) 匹配,与 NOT 等价。 - should
至少有一个语句要匹配,与 OR 等价。
GET /my_store/products/_search
{
"query" : {
"bool" : {
"should" : [
{ "term" : {"price" : 20}},
{ "term" : {"productID" : "XHDK-A-1293-#fJ3"}}
],
"must_not" : {
"term" : {"price" : 30}
}
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。