ES 複雜類型及其查詢

1、關於對象類型的操作和查詢

創建索引,插入數據

PUT /blog
{
  "mappings": {
    "properties": {
      "Content":{
        "type": "text"
      },
      "CreateTime":{
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss"
      },
      "Author":{
        "properties": {
          "UserName":{
            "type":"keyword"
          },
           "Adress": {
            "type": "text"
          }
        }
      }
    }
  }
}

PUT blog/_doc/1
{
  "Content":"i learn Elasticsearch",
  "time":"2020-01-01 00:00:00",
  "Author":{
    "UserName":"mark",
    "Adress":"hangzhou"
  }
}

現在需要統計作爲爲mark,文章內容爲Elasticsearch的文檔記錄,代碼如下:

GET blog/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {
          "Content": "Elasticsearch"
        }},{
          "match": {
            "Author.UserName": "mark"
          }
        }
      ]
    }
  }
}

搜索結果如下:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.5753642,
    "hits" : [
      {
        "_index" : "blog",
        "_id" : "1",
        "_score" : 0.5753642,
        "_source" : {
          "Content" : "i learn Elasticsearch",
          "time" : "2020-01-01 00:00:00",
          "Author" : {
            "UserName" : "mark",
            "Adress" : "hangzhou"
          }
        }
      }
    ]
  }
}

當嵌套對象只有一個時,搜索是正常的,但是注意下面關於2的用法

 

2、關於對象數組的操作

PUT /blog
{
  "mappings": {
    "properties": {
      "Content":{
        "type": "text"
      },
      "CreateTime":{
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss"
      },
      "Author":{
        "properties": {
          "UserName":{
            "type":"keyword"
          },
           "Adress": {
            "type": "text"
          }
        }
      }
    }
  }
}

PUT blog/_doc/1
{
  "Content":"i learn Elasticsearch",
  "time":"2020-01-01 00:00:00",
  "Author":[
    {
    "UserName":"mark",
    "Adress":"hangzhou"
    },
  {
    "UserName":"jerry",
    "Adress":"shanghai"
  }
    ]
}

當博客存在兩個作者時,此時需要搜索作者名爲mark,且聯繫地址時shanghai的記錄,顯然是不存在的,代碼如下:

GET blog/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {
          "Author.Adress": "shanghai"
        }},{
          "match": {
            "Author.UserName": "mark"
          }
        }
      ]
    }
  }
}

搜索結果如下:

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.64933956,
    "hits" : [
      {
        "_index" : "blog",
        "_id" : "1",
        "_score" : 0.64933956,
        "_source" : {
          "Content" : "i learn Elasticsearch",
          "time" : "2020-01-01 00:00:00",
          "Author" : [
            {
              "UserName" : "mark",
              "Adress" : "hangzhou"
            },
            {
              "UserName" : "jerry",
              "Adress" : "shanghai"
            }
          ]
        }
      }
    ]
  }
}

此時,存在結果,顯示是不對的.這裏看官方的介紹,當將字段描述成object類型時,存入的數組對象,es會移除對象數組中對象屬性之間的關聯關係,也就是說如下代碼:

{
     "UserName" : "mark",
     "Adress" : "hangzhou"
}

es會移除UserName和Adress的關聯關係,彼此是獨立的,從而建立如下關係

{
  "Author.Adress" : [ "hangzhou", "shanghai" ],
  "Author.UserName" :  [ "mark", "jerry" ]
}

所以失去了關聯關係之後的搜索,只能按照keyvalue的形式進行搜索,從而返回值,所以這裏must查詢可以查詢到結果,所以解決這個問題,只能通過將字段描述成Nested類型

 

3、Nested類型

3.1 解決object的問題

PUT /blog
{
  "mappings": {
    "properties": {
      "Content":{
        "type": "text"
      },
      "CreateTime":{
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss"
      },
      "Author":{
        "type": "nested", 
        "properties": {
          "UserName":{
            "type":"keyword"
          },
           "Adress": {
            "type": "text"
          }
        }
      }
    }
  }
}

PUT blog/_doc/1
{
  "Content":"i learn Elasticsearch",
  "time":"2020-01-01 00:00:00",
  "Author":[
    {
    "UserName":"mark",
    "Adress":"hangzhou"
    },
  {
    "UserName":"jerry",
    "Adress":"shanghai"
  }
    ]
}

因爲2中存在的問題,此時將Author描述成Nested類型,在執行如下搜索

GET blog/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {
          "Author.Adress": "shanghai"
        }},{
          "match": {
            "Author.UserName": "mark"
          }
        }
      ]
    }
  }
}

結果如下:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

此時結果正確,Nested類型的文檔會被保存在兩個Lucene文檔中,查詢時做 join 處理

 

3.2 通過nested實現類似關係型數據庫的join關聯條件限制查詢

查詢文章內容中包含Elasticsearch且作者爲mark的記錄

GET blog/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "Content": "Elasticsearch"
          }
        },
        {
          "nested": {
            "path": "Author",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "Author.UserName": "mark"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

結果如下:

{
  "took" : 222,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.3862944,
    "hits" : [
      {
        "_index" : "blog",
        "_id" : "2",
        "_score" : 1.3862944,
        "_source" : {
          "Content" : "i learn Elasticsearch",
          "time" : "2020-01-01 00:00:00",
          "Author" : [
            {
              "UserName" : "scott",
              "Adress" : "newyork"
            },
            {
              "UserName" : "sam",
              "Adress" : "english"
            }
          ]
        }
      }
    ]
  }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章