­

ElasticSearch7.3學習(二十一)—-Filter與Query對比、使用explain關鍵字分析語法

1、數據準備

首先創建book索引

PUT /book/
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
      },
      "description": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
      },
      "studymodel": {
        "type": "keyword"
      },
      "price": {
        "type": "double"
      },
      "timestamp": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      },
      "pic": {
        "type": "text",
        "index": false
      }
    }
  }
}

插入數據

PUT /book/_doc/1
{
  "name": "Bootstrap開發",
  "description": "Bootstrap是一個非常流行的開發框架。此開發框架可以幫助不擅長css頁面開發的程序人員輕鬆的實現一個css,不受瀏覽器限制的精美界面css效果。",
  "studymodel": "201002",
  "price": 38.6,
  "timestamp": "2019-08-25 19:11:35",
  "pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
  "tags": [
    "bootstrap",
    "dev"
  ]
}

PUT /book/_doc/2
{
  "name": "java編程思想",
  "description": "java語言是世界第一編程語言,在軟件開發領域使用人數最多。",
  "studymodel": "201001",
  "price": 68.6,
  "timestamp": "2019-08-25 19:11:35",
  "pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
  "tags": [
    "java",
    "dev"
  ]
}

PUT /book/_doc/3
{
  "name": "spring開發基礎",
  "description": "spring 在java領域非常流行,java程序員都在用。",
  "studymodel": "201001",
  "price": 88.6,
  "timestamp": "2019-08-24 19:11:35",
  "pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
  "tags": [
    "spring",
    "java"
  ]
}

2、Filter與Query示例

需求:用戶查詢description中有”java程序員”,並且價格大於80小於90的數據。

2.1 Query

首先採用Query來進行查詢,首先查詢description中有”java程序員”。

GET /book/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "description": "java程序員"
          }
        }
      ]
    }
  }
}

查詢結果如下:

可以看到,查詢出來兩條數據,score分別是1.9、0.5。

然後查詢description中有”java程序員”,並且價格大於80小於90的數據

GET /book/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "description": "java程序員"
          }
        },
        {
          "range": {
            "price": {
              "gte": 80,
              "lte": 90
            }
          }
        }
      ]
    }
  }
}

再次查看結果:

這次查詢出來一條數據,score變為2.9。這一條數據在上一次的查詢結果中的score為1.9。然後接着往下看使用Filter。

2.2 filter

還是相同的需求,首先查詢description中有”java程序員”。

GET /book/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "description": "java程序員"
          }
        }
      ]
    }
  }
}

查詢結果如下:

通過查詢結果可以看到,查詢的兩條數據的score是1.9、0.5。

然後使用filter查詢description中有”java程序員”,並且價格大於80小於90的數據

GET /book/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "description": "java程序員"
          }
        }
      ],
      "filter": {
        "range": {
          "price": {
            "gte": 80,
            "lte": 90
          }
        }
      }
    }
  }
}

查詢結果如下:

可以看到,查詢出來的數據與使用query查詢結果一樣,但是score依舊為1.9。

說明在使用query查詢的過程中,影響到了相關度(score)的排序,在使用filter進行查詢,並不會影響相關度(score)的計算。

2.3  filter與query對比

filter,僅僅只是按照搜索條件過濾出需要的數據而已,不計算任何相關度分數,對相關度沒有任何影響。

query,會去計算每個document相對於搜索條件的相關度,並按照相關度進行排序。

應用場景:

一般來說,如果你是在進行搜索,需要將最匹配搜索條件的數據先返回,那麼用query。如果你只是要根據一些條件篩選出一部分數據,不關注其排序,那麼用filter。

2.4 filter與query性能

filter,不需要計算相關度分數,不需要按照相關度分數進行排序,同時還有內置的自動cache最常使用filter的數據。比如在範圍查詢,keyword字段查詢中推薦使用filter來進行查詢。

query,相反,要計算相關度分數,按照分數進行排序,而且無法cache結果。

在同等查詢結果下,filter的性能一般是要優於query的。

3、explain分析語法

在實際的應用過程中,需要查詢的邏輯一般比較複雜,那當語句冗長的時候,這時候顯然不太可能通過直接執行語句來調試語法正確與否,這個時候就可以通過explain來驗證語句的正確性。

驗證錯誤語句:

GET /book/_validate/query?explain
{
  "query": {
    "mach": {
      "description": "java程序員"
    }
  }
}

返回結果如下,錯誤信息為沒有名叫mach的query。

{
  "valid" : false,
  "error" : "org.elasticsearch.common.ParsingException: no [query] registered for [mach]"
}

再來看語句正確的情況下

GET /book/_validate/query?explain
{
  "query": {
    "match": {
      "description": "java程序員"
    }
  }
}

返回,返回結果還包含對語句的解釋:從description查詢java關鍵詞,從description查詢程序員關鍵詞。

{
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "valid" : true,
  "explanations" : [
    {
      "index" : "book",
      "valid" : true,
      "explanation" : "description:java description:程序員"
    }
  ]
}

應用場景:

一般用在那種特別複雜龐大的搜索下,比如你一下子寫了上百行的搜索,這個時候可以先用validate api去驗證一下,搜索是否合法。合法以後,explain就像mysql的執行計劃,可以看到搜索的目標等信息。