學習整理自官方文檔
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