Elasticsearch筆記2

學習整理自官方文檔

搜索所有文檔

可以使用如下的命令來搜索到所有的文檔:
GET /_search

沒有指定任何index,將搜索在該cluster下的所有的index。目前默認的返回個數是10個,除非設定size:
GET /_search?size=20

如果只想搜索特定的index,比如twitter,我們可以這麼做:
GET twitter/_search
在這裏插入圖片描述
從上面可以看出來,在twitter index裏我們有4個文檔。在上面的hits數組裏,可以看到所有的結果。同時也可以看到一個叫做_score的項。它表示我們搜索結果的相關度。這個分數值越高,表明我們搜索匹配的相關度越高。在默認沒有sort的情況下,所有搜索的結果的是按照分數由大到小來進行排列的。

在默認的情況下,可以得到10個結果,通過設置size參數得到想要的個數。同時可以也配合from來進行page。

GET twitter/_search?size=2&from=2

等同於

GET twitter/_search
{
  "size": 2,
  "from": 2, 
  "query": {
    "match_all": {}
  }
}

都是將數據分爲兩頁,每頁顯示兩個文檔

source filtering

  • 可以通過_source來定義返回想要的字段:
GET 索引/_search
{
  "_source": ["字段1", "字段2"],
  "query": {
    "match_all": {
    }
  }
}

在這裏插入圖片描述
可以看到只有user及city兩個字段在_source裏返回。

  • 可以通過設置_source爲false,不返回任何的_source信息:
GET 索引/_search
{
  "_source": false,
  "query": {
    "match": {
      "匹配字段": "匹配數據"
    }
  }
}

在這裏插入圖片描述
可以看到只有_id及_score等信息返回。其它任何的_source字段都沒有被返回。

  • 可以接收通配符形式的控制:
GET 索引/_search
{
  "_source": {
    "includes": [
      "匹配字段1*",
      "匹配字段2*"
    ],
    "excludes": [
      "*.lat"
    ]
  },
  "query": {
    "match_all": {}
  }
}

在這裏插入圖片描述

Script fields

有些時候,想要的field可能在_source里根本沒有,那麼可以使用script field來生成這些field。允許爲每個匹配返回script evaluation(基於不同的字段),例如:
在這裏插入圖片描述
必須注意的是這種使用script的方法來生成查詢的結果對於大量的文檔來說,可能會佔用大量資源。

Count API

  • 經常會查詢索引裏到底有多少文檔,那麼可以使用_count重點來查詢:
    GET 索引/_count
  • 想知道滿足條件的文檔的數量,可以採用如下的格式:
GET 索引/_count
{
  "query": {
    "match": {
      "匹配字段": "匹配數據"
    }
  }
}

修改settings

  • 可以通過如下的接口來獲得一個index的settings
    GET 索引/_settings
    在這裏插入圖片描述
    從這裏可以看到twitter index有多少個shards及多少個replicas。
  • 也可以通過如下的接口來設置:
PUT 索引
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 1
  }
}

在這裏插入圖片描述
一旦把number_of_shards定下來了,就不可以修改了,除非把index刪除,並重新index它。這是因爲每個文檔存儲到哪一個shard是和number_of_shards這個數值有關的。一旦這個數值發生改變,那麼之後尋找那個文檔所在的shard就會不準確。

修改index的mapping

Elasticsearch號稱是schemaless,在實際所得應用中,每一個index都有一個相應的mapping。這個mapping在我們生產第一個文檔時已經生產。它是對每個輸入的字段進行自動的識別從而判斷它們的數據類型。我們可以這麼理解schemaless:

不需要事先定義一個相應的mapping纔可以生產文檔。字段類型是動態進行識別的。這和傳統的數據庫是不一樣的

如果有動態加入新的字段,mapping也可以自動進行調整並識別新加入的字段

自動識別字段有一個問題,那就是有的字段可能識別並不精確,比如對於例子中的位置信息。那麼需要對這個字段進行修改。

可以通過如下的命令來查詢目前的index的mapping:
GET 索引/_mapping

在這裏插入圖片描述
注意:不能爲已經建立好的index動態修改mapping。這是因爲一旦修改,那麼之前建立的索引就變成不能搜索的了。一種辦法是reindex從而重新建立索引。如果在之前的mapping加入新的字段,那麼可以不用重新建立索引。

查詢數據

match query

GET 索引/_search
{
  "query": {
    "match": {
      "匹配字段": "匹配數據"
    }
  }
}

在這裏插入圖片描述
從查詢的結果來看,我們可以看到有3個用戶是來自北京的,而且查詢出來的結果是按照關聯(relavance)來進行排序的。

如果不需要這個score,可以選擇filter來完成。

GET 索引/_search
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "匹配字段.keyword": "匹配數據"
        }
      }
    }
  }
}

在這裏插入圖片描述
從返回的結果來看,_score項爲0。對於這種搜索,只要yes或no。我們並不關心它們是的相關性。在這裏使用了city.keyword。正確的理解是city在mapping中是一個multi-field項。它既是text也是keyword類型。對於一個keyword類型的項來說,這個項裏面的所有字符都被當做一個字符串。它們在建立文檔時,不需要進行index。keyword字段用於精確搜索,aggregation和排序(sorting)。

所以在filter中,是使用了term來完成這個查詢。

也可以使用如下的辦法達到同樣的效果:

GET 索引/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "匹配字段": {
            "value": "匹配數據"
          }
        }
      }
    }
  }
}
  • 在使用match query時,默認的操作是OR,可以做如下的查詢:
GET 索引/_search
{
  "query": {
    "match": {
      "user": {
        "query": "ABCDE",
        "operator": "or"
      }
    }
  }
}

上面的查詢也和如下的查詢是一樣的:

GET 索引/_search
{
 "query": {
   "match": {
     "user": "ABCDE"
   }
 }
}

這是因爲默認的操作是or操作。上面查詢的結果是任何文檔匹配A,B,C,D,E中的一個都將被顯示。

  • 可以設置參數minimum_should_match來設置至少匹配的term。比如:
GET 索引/_search
{
  "query": {
    "match": {
      "user": {
        "query": "ABCDE",
        "operator": "or",
        "minimum_should_match": 3
      }
    }
  }
}

上面顯示至少要匹配A,B,C,D,E這5箇中的3個字纔可以。

  • 可以改爲"and“,在這種情況下,需要同時匹配索引的5個字纔可以。顯然我們可以通過使用and來提高搜索的精度。
```javascript
GET 索引/_search
{
  "query": {
    "match": {
      "user": {
        "query": "ABCDE",
        "operator": "and"
      }
    }
  }
}

Multi_match

在上面的搜索之中,特別指明一個專有的field來進行搜索,但是在很多的情況下,並不知道是哪一個field含有這個關鍵詞,那麼在這種情況下,可以使用multi_match來進行搜索:

GET 索引/_search
{
  "query": {
    "multi_match": {
      "query": "匹配數據",
      "fields": [
        "匹配字段1",
        "匹配字段2^3",
        "匹配字段3"
      ],
      "type": "best_fields"
    }
  }
}

在上面,同時對三個字段進行搜索,但是對字段2含有匹配數據的文檔的分數進行3倍的加權。

Prefix query

返回在提供的字段中包含特定前綴的文檔。

GET 索引/_search
{
  "query": {
    "prefix": {
      "匹配字段": {
        "value": "匹配前綴"
      }
    }
  }
}

Terms query

如果想對多個terms進行查詢,可以使用如下的方式來進行查詢:

GET 索引/_search
{
  "query": {
    "terms": {
      "匹配字段.keyword": [
        "匹配數據1",
        "匹配數據2"
      ]
    }
  }
}

上面查詢字段.keyword裏含有匹配數據1,2的所有文檔。

複合查詢(compound query)

什麼是複合查詢呢?如果說上面的查詢是leaf查詢的話,那麼複合查詢可以把很多個leaf查詢組合起來從而形成更爲複雜的查詢。它一般的格式是:

POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user" : "kimchy" }
      },
      "filter": {
        "term" : { "tag" : "tech" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tag" : "wow" } },
        { "term" : { "tag" : "elasticsearch" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}

從上面我們可以看出,它是由bool下面的must, must_not, should及filter共同來組成的。針對例子:

must

在這裏插入圖片描述
這個查詢的是必須是 北京城市的,並且年剛好是30歲的。

  • 如果我們想知道爲什麼得出來這樣的結果,可以在搜索的指令中加入"explained" : true。在的顯示的結果中,可以看到一些解釋:
    在這裏插入圖片描述

must_not

同樣,可以使用must_not把一些滿足條件的排出在外。
尋找不在北京的所有的文檔:
在這裏插入圖片描述

should

它表述“或”的意思,也就是有就更好,沒有就算了。比如這個搜尋的意思是,age必須是30歲,但是如果文檔裏含有“Hanppy birthday”,相關性會更高,那麼搜索得到的結果會排在前面:
在這裏插入圖片描述

範圍查詢

在ES中,可以進行範圍查詢。根據設定的範圍來對數據進行查詢:
查詢年齡介於30到40歲的文檔:
在這裏插入圖片描述
同樣地,可以對整個搜索的結果按照降序進行排序:
在這裏插入圖片描述

Exists 查詢

通過exists來查詢一個字段是否存在。比如再增加一個文檔,在這個文檔裏,city這一個字段是不存在的,那麼以下的這個搜索將不會返回上面的這個文檔。

在這裏插入圖片描述
只要文檔裏city這個字段不爲空,那麼就會被返回。反之,如果一個文檔裏city這個字段是空的,那麼就不會返回。

如果查詢不含指定字段的所有的文檔,可以這樣查詢:

GET 索引/_search
{
  "query": {
    "bool": {
      "must_not": {
        "exists": {
          "field": "匹配字段"
        }
      }
    }
  }
}

匹配短語

通過如下的方法來查找happy birthday
在這裏插入圖片描述

  • 在默認的情況下,這個匹配是“或”的關係,也就是找到文檔裏含有“Happy"或者“birthday”的文檔。如果新增加一個文檔,重新進行搜索,可以看到這個新增加的id爲8的也會在搜索出的結果之列,雖然它只含有“Happy"在message裏。在這裏插入圖片描述
  • 如果想得到“與”的關係,可以採用如下的辦法:
GET 索引/_search
{
  "query": {
    "match": {
      "message": {
        "query": "匹配數據",
        "operator": "and"
      }
    }
  }
}
  • 可以看到在搜索到的結果中,無論搜索的是大小寫字母,在搜索的時候都可以匹配到,並且在message中,happy birthday這兩個詞的先後順序也不是很重要。
    比如,把id爲5的文檔BirthDay弄到Happy的前面
    在這裏插入圖片描述
    顯然,match查詢時時不用分先後順序的。
  • 使用match_phrase。它要求Happy必須是在birthday的前面。
    在這裏插入圖片描述
  • 把之前的那個id爲5的文檔在Happy 和Birthday之前加入一個Good。用之前的那個match_phrase是找不到這個文檔的。爲了能夠找到上面這個修正的結果,使用了slop:1,表面Happy和birthday之前是可以允許一個token的差別。
  • 在這裏插入圖片描述

Named queries

使用_name爲一個filter或query來取一個名字,比如:
在這裏插入圖片描述
從上面的返回結果可以看出來多了一個叫做matched_queries的字段。在它的裏面羅列了每個匹配到的查詢。

多個索引操作

  • 對所有的以pre爲開頭的索引來進行搜索,顯示的結果是在所有的pre1,pre2…t中的文檔:
    GET pre*/_search
  • 另一種方法,在兩個索引之間不能加入空格
    GET /twitter,twitter1/_search
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章