概念
结构化数据,在Elasticsearch中叫Structured Data,用于表示一个不可分割的值。相对于全文本的分词处理,结构化数据本身可看成一个整体。
结构化数据包括:
- 日期
- 布尔类型
- 数字
- 分词无意义的文本,包括可枚举的文本
- 颜色的种类,如:红、黄、蓝、绿、黑
- 博客的标签,如:Java、Elasticsearch、C语言
- 性别,如:男性、女性、保密、未知
- 订单的id
因此,结构化数据的搜索叫做结构化搜索,可以做精准匹配或者部分匹配。精准匹配使用Term查询,部分匹配使用Prefix前缀查询。结构化搜索的结果只有是
和否
两个结果。实际场景中,我们根据需要,可以选择是否对搜索的结果进行相关性算分。
例子
先批量导入一些数据。
# 结构化搜索,精确匹配
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" }
再来看看字段的类型,price为long类型,avaliable为boolean类型,date为日期类型,productID为text全文本类型。
GET products/_mapping
对boolean类型查询如下所示。同时,我们可以通过constant score 转成 filtering的方式,来避免算分的过程,也能有效地利用缓存来提高性能。
# 对布尔值 match 查询,有算分
POST products/_search
{
"profile": "true",
"explain": true,
"query": {
"term": {
"avaliable": true
}
}
}
# 对布尔值,通过constant score 转成 filtering,没有算分
POST products/_search
{
"profile": "true",
"explain": true,
"query": {
"constant_score": {
"filter": {
"term": {
"avaliable": true
}
}
}
}
}
数字类型的查询如下所示。
# 数字类型 Term
POST products/_search
{
"profile": "true",
"explain": true,
"query": {
"term": {
"price": 30
}
}
}
# 数字类型 terms
POST products/_search
{
"query": {
"constant_score": {
"filter": {
"terms": {
"price": [
"20",
"30"
]
}
}
}
}
}
# 数字 Range 查询
GET products/_search
{
"query" : {
"constant_score" : {
"filter" : {
"range" : {
"price" : {
"gte" : 20,
"lte" : 30
}
}
}
}
}
}
我们可以对日期类型进行范围查询。有意思的是,这儿我们可以使用now、y、M、h等特殊的单词,加上一些操作符号来完成一些简单的计算。下面的例子表示查找过去一年的数据。
- 日期范围查找参考:Using the range query with date fields
- 日期匹配参考:date-math
# 日期 range
POST products/_search
{
"query" : {
"constant_score" : {
"filter" : {
"range" : {
"date" : {
"gte" : "now-1y"
}
}
}
}
}
}
判断字段是否存在,可如下查询。
# exists查询
POST products/_search
{
"query": {
"constant_score": {
"filter": {
"exists": {
"field": "date"
}
}
}
}
}
对于多值查询,通常是包含,而非等于。若想达到等于的效果,需要使用boolean查询
+数量判断
来间接实现。
# 处理多值字段
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"
}
}
}
}
}
总结
通过学习,我们知道了结构化数据的含义,也了解了结构化数据的查询(其实就是term查询及其各种变种)。对于多值查询,通常是包含关系,而非等于。若要实现多值查询的等于功能,需要使用boolean查询
+数量判断
来间接实现。
网友评论