Elasticsearch常用查詢


文檔
在Elasticsearch中,文檔以JSON格式進行存儲,可以是復雜的結構,如:

{
    "_index": "haoke",
    "_type": "user",
    "_id": "1001",
    "_version": 1,
    "found": true,
    "_source": {
        "id": 1001,
        "name": "張三",
        "age": 21,
        "sex": ""
    }
}

元數據(metadata)
一個文檔不只有數據。它還包含了元數據(metadata)——關於文檔的信息。三個必須的元數據節點是:

_index

  • 索引(index)類似於關系型數據庫里的“數據庫”——它是我們存儲和索引關聯數據的地方。

         提示:事實上,我們的數據被存儲和索引在分片(shards)中,索引只是一個把一個或多個分片分組在一起的邏輯空間。然而,這只是一些內部細節——我們的程序完全不用關心分片。

_type

  • 在應用中,我們使用對象表示一些“事物”,例如一個用戶、一篇博客、一個評論,或者一封郵件。每個對象都屬於一個類(class),這個類定義了屬性或與對象關聯的數據。 user 類的對象可能包含姓名、性別、年齡和Email地址。
  • 在關系型數據庫中,我們經常將相同類的對象存儲在一個表里,因為它們有着相同的結構。同理,在Elasticsearch中,我們使用相同類型(type)的文檔表示相同的“事物”,因為他們的數據結構也是相同的。
  • 每個類型(type)都有自己的映射(mapping)或者結構定義,就像傳統數據庫表中的列一樣。所有類型下的文檔被存儲在同一個索引下,但是類型的映射(mapping)會告訴Elasticsearch不同的文檔如何被索引。
  • _type 的名字可以是大寫或小寫,不能包含下划線或逗號。我們將使用 blog 做為類型名。

_id

  • id僅僅是一個字符串,它與 _index 和 _type 組合時,就可以在Elasticsearch中唯一標識一個文檔。當創建一個文檔,你可以自定義 _id ,也可以讓Elasticsearch幫你自動生成(32位長度)。

查詢響應

pretty
可以在查詢url后面添加pretty參數,使得返回的json更易查看。

指定響應字段

在響應的數據中,如果我們不需要全部的字段,可以指定某些需要的字段進行返回。

http://121.40.152.53:9200/haoke/user/1001?_source=id,name

 

 如不需要返回元數據,僅僅返回原始數據,可以這樣:

 還可這樣:

判斷文檔是否存在
如果我們只需要判斷文檔是否存在,而不是查詢文檔內容,那么可以這樣:

 

當然,這只表示你在查詢的那一刻文檔不存在,但並不表示幾毫秒后依舊不存在。另一個進程在這期間可能創建新文檔。

批量查詢

{
    "docs": [
        {
            "_index": "haoke",
            "_type": "user",
            "_id": "1001",
            "_version": 1,
            "found": true,
            "_source": {
                "id": 1001,
                "name": "張三",
                "age": 21,
                "sex": ""
            }
        },
        {
            "_index": "haoke",
            "_type": "user",
            "_id": "1002",
            "_version": 1,
            "found": true,
            "_source": {
                "id": 1001,
                "name": "張三1",
                "age": 22,
                "sex": ""
            }
        }
    ]
}

如果,某一條數據不存在,不影響整體響應,需要通過found的值進行判斷是否查詢到數據。

_bulk操作
在Elasticsearch中,支持批量的插入、修改、刪除操作,都是通過_bulk的api完成的。
請求格式如下:(請求格式不同尋常)

 結果:

{
    "took": 71,
    "errors": false,
    "items": [
        {
            "create": {
                "_index": "haoke",
                "_type": "user",
                "_id": "2001",
                "_version": 1,
                "result": "created",
                "_shards": {
                    "total": 1,
                    "successful": 1,
                    "failed": 0
                },
                "created": true,
                "status": 201
            }
        },
        {
            "create": {
                "_index": "haoke",
                "_type": "user",
                "_id": "2002",
                "_version": 1,
                "result": "created",
                "_shards": {
                    "total": 1,
                    "successful": 1,
                    "failed": 0
                },
                "created": true,
                "status": 201
            }
        },
        {
            "create": {
                "_index": "haoke",
                "_type": "user",
                "_id": "2003",
                "_version": 1,
                "result": "created",
                "_shards": {
                    "total": 1,
                    "successful": 1,
                    "failed": 0
                },
                "created": true,
                "status": 201
            }
        }
    ]
}

批量刪除:

 結果:

{
    "took": 3,
    "errors": false,
    "items": [
        {
            "delete": {
                "found": true,
                "_index": "haoke",
                "_type": "user",
                "_id": "2001",
                "_version": 2,
                "result": "deleted",
                "_shards": {
                    "total": 1,
                    "successful": 1,
                    "failed": 0
                },
                "status": 200
            }
        },
        {
            "delete": {
                "found": true,
                "_index": "haoke",
                "_type": "user",
                "_id": "2002",
                "_version": 2,
                "result": "deleted",
                "_shards": {
                    "total": 1,
                    "successful": 1,
                    "failed": 0
                },
                "status": 200
            }
        },
        {
            "delete": {
                "found": true,
                "_index": "haoke",
                "_type": "user",
                "_id": "2003",
                "_version": 2,
                "result": "deleted",
                "_shards": {
                    "total": 1,
                    "successful": 1,
                    "failed": 0
                },
                "status": 200
            }
        }
    ]
}

一次請求多少性能最高?
整個批量請求需要被加載到接受我們請求節點的內存里,所以請求越大,給其它請求可用的內存就越小。有一
個最佳的bulk請求大小。超過這個大小,性能不再提升而且可能降低。
最佳大小,當然並不是一個固定的數字。它完全取決於你的硬件、你文檔的大小和復雜度以及索引和搜索的負載。
幸運的是,這個最佳點(sweetspot)還是容易找到的:試着批量索引標准的文檔,隨着大小的增長,當性能開始
降低,說明你每個批次的大小太大了。開始的數量可以在1000~5000個文檔之間,如果你的文檔非常大,可以
使用較小的批次。
通常着眼於你請求批次的物理大小是非常有用的。一千個1kB的文檔和一千個1MB的文檔大不相同。一個好的
批次最好保持在5-15MB大小間。

分頁
和SQL使用 LIMIT 關鍵字返回只有一頁的結果一樣,Elasticsearch接受 from 和 size 參數:

size: 結果數,默認10
from: 跳過開始的結果數,默認0
http://121.40.152.53:9200/haoke/user/_search?size=2&from=1
{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 2,
        "successful": 2,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 3,
        "max_score": 1.0,
        "hits": [
            {
                "_index": "haoke",
                "_type": "user",
                "_id": "1002",
                "_score": 1.0,
                "_source": {
                    "id": 1001,
                    "name": "張三1",
                    "age": 22,
                    "sex": ""
                }
            },
            {
                "_index": "haoke",
                "_type": "user",
                "_id": "1003",
                "_score": 1.0,
                "_source": {
                    "id": 1003,
                    "name": "張1",
                    "age": 25,
                    "sex": ""
                }
            }
        ]
    }
}

映射

前面我們創建的索引以及插入數據,都是由Elasticsearch進行自動判斷類型,有些時候我們是需要進行明確字段類型的,否則,自動判斷的類型和實際需求是不相符的。
自動判斷的規則如下:

JSON type Field type
Boolean: true or false "boolean"
Whole number: 123 "long"
Floating point: 123.45 "double"
String, valid date: "2014-09-15" "date"
String: "foo bar" "string"

 Elasticsearch中支持的類型如下:

類型 表示的數據類型
String string , text , keyword
Whole number byte , short , integer , long
Floating point float , double
Boolean boolean
Date date

string類型在ElasticSearch 舊版本中使用較多,從ElasticSearch 5.x開始不再支持string,由text和keyword類型替代。
text 類型,當一個字段是要被全文搜索的,比如Email內容、產品描述,應該使用text類型。設置text類型
以后,字段內容會被分析,在生成倒排索引以前,字符串會被分析器分成一個一個詞項。text類型的字段
不用於排序,很少用於聚合。
keyword類型適用於索引結構化的字段,比如email地址、主機名、狀態碼和標簽。如果字段需要進行過
(比如查找已發布博客中status屬性為published的文章)、排序、聚合。keyword類型的字段只能通過精
確值搜索到。

http://121.40.152.53:9200/dalianpai
{
  "settings": {
    "index": {
      "number_of_shards": "2",
      "number_of_replicas": "0"
    }
  },
  "mappings": {
    "person": {
      "properties": {
        "name": {
          "type": "text"
        },
        "age": {
          "type": "integer"
        },
        "mail": {
          "type": "keyword"
        },
        "hobby": {
          "type": "text"
        }
      }
    }
  }
}

 查看映射:

http://121.40.152.53:9200/dalianpai/_mapping

 插入數據:

 結果:

 

 結果:

{
    "took": 10,
    "timed_out": false,
    "_shards": {
        "total": 2,
        "successful": 2,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 2,
        "max_score": 1.3773504,
        "hits": [
            {
                "_index": "dalianpai",
                "_type": "person",
                "_id": "AXFeHQMrEXg1j8gSlZhA",
                "_score": 1.3773504,
                "_source": {
                    "name": "孫七",
                    "age": 24,
                    "mail": "555@qq.com",
                    "hobby": "聽音樂、看電影"
                }
            },
            {
                "_index": "dalianpai",
                "_type": "person",
                "_id": "AXFeHQMrEXg1j8gSlZg-",
                "_score": 1.1655893,
                "_source": {
                    "name": "王五",
                    "age": 22,
                    "mail": "333@qq.com",
                    "hobby": "羽毛球、籃球、游泳、聽音樂"
                }
            }
        ]
    }
}

term查詢
term 主要用於精確匹配哪些值,比如數字,日期,布爾值或 not_analyzed 的字符串(未經分析的文本數據類型):

 結果:

{
    "took": 31,
    "timed_out": false,
    "_shards": {
        "total": 2,
        "successful": 2,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 1.0,
        "hits": [
            {
                "_index": "dalianpai",
                "_type": "person",
                "_id": "AXFeHQMrEXg1j8gSlZg8",
                "_score": 1.0,
                "_source": {
                    "name": "張三",
                    "age": 20,
                    "mail": "111@qq.com",
                    "hobby": "羽毛球、乒乓球、足球"
                }
            }
        ]
    }
}

terms查詢
terms 跟 term 有點類似,但 terms 允許指定多個匹配條件。 如果某個字段指定了多個值,那么文檔需要一起去做匹配:

 結果:

{
    "took": 2,
    "timed_out": false,
    "_shards": {
        "total": 2,
        "successful": 2,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 2,
        "max_score": 1.0,
        "hits": [
            {
                "_index": "dalianpai",
                "_type": "person",
                "_id": "AXFeHQMrEXg1j8gSlZg9",
                "_score": 1.0,
                "_source": {
                    "name": "李四",
                    "age": 21,
                    "mail": "222@qq.com",
                    "hobby": "羽毛球、乒乓球、足球、籃球"
                }
            },
            {
                "_index": "dalianpai",
                "_type": "person",
                "_id": "AXFeHQMrEXg1j8gSlZg8",
                "_score": 1.0,
                "_source": {
                    "name": "張三",
                    "age": 20,
                    "mail": "111@qq.com",
                    "hobby": "羽毛球、乒乓球、足球"
                }
            }
        ]
    }
}

range查詢
range 過濾允許我們按照指定范圍查找一批數據:

范圍操作符包含:
gt :: 大於
gte :: 大於等於
lt :: 小於
lte :: 小於等於

示例:

 結果:

{
    "took": 4,
    "timed_out": false,
    "_shards": {
        "total": 2,
        "successful": 2,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 3,
        "max_score": 1.0,
        "hits": [
            {
                "_index": "dalianpai",
                "_type": "person",
                "_id": "AXFeHQMrEXg1j8gSlZg9",
                "_score": 1.0,
                "_source": {
                    "name": "李四",
                    "age": 21,
                    "mail": "222@qq.com",
                    "hobby": "羽毛球、乒乓球、足球、籃球"
                }
            },
            {
                "_index": "dalianpai",
                "_type": "person",
                "_id": "AXFeHQMrEXg1j8gSlZg8",
                "_score": 1.0,
                "_source": {
                    "name": "張三",
                    "age": 20,
                    "mail": "111@qq.com",
                    "hobby": "羽毛球、乒乓球、足球"
                }
            },
            {
                "_index": "dalianpai",
                "_type": "person",
                "_id": "AXFeHQMrEXg1j8gSlZg-",
                "_score": 1.0,
                "_source": {
                    "name": "王五",
                    "age": 22,
                    "mail": "333@qq.com",
                    "hobby": "羽毛球、籃球、游泳、聽音樂"
                }
            }
        ]
    }
}

exists 查詢
exists 查詢可以用於查找文檔中是否包含指定字段或沒有某個字段,類似於SQL語句中的 IS_NULL 條件

 結果:

 

match查詢

match 查詢是一個標准查詢,不管你需要全文本查詢還是精確查詢基本上都要用到它。
如果你使用 match 查詢一個全文本字段,它會在真正查詢之前用分析器先分析 match 一下查詢字符:

 結果:

{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 2,
        "successful": 2,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 0.25811607,
        "hits": [
            {
                "_index": "dalianpai",
                "_type": "person",
                "_id": "AXFeHQMrEXg1j8gSlZg9",
                "_score": 0.25811607,
                "_source": {
                    "name": "李四",
                    "age": 21,
                    "mail": "222@qq.com",
                    "hobby": "羽毛球、乒乓球、足球、籃球"
                }
            }
        ]
    }
}

bool查詢
bool 查詢可以用來合並多個條件查詢結果的布爾邏輯,它包含一下操作符:
must :: 多個查詢條件的完全匹配,相當於 and 。
must_not :: 多個查詢條件的相反匹配,相當於 not 。
should :: 至少有一個查詢條件匹配, 相當於 or 。
這些參數可以分別繼承一個查詢條件或者一個查詢條件的數組:

{
  "bool": {
    "must":   { "term": { "folder": "inbox" }},
    "must_not": { "term": { "tag":   "spam" }},
    "should": [
         { "term": { "starred": true  }},
         { "term": { "unread":  true  }}
   ]
 }
}

過濾查詢
Elasticsearch也支持過濾查詢,如term、range、match等。
示例:查詢年齡為20歲的用戶。

 

結果:

{
    "took": 3,
    "timed_out": false,
    "_shards": {
        "total": 2,
        "successful": 2,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 0.0,
        "hits": [
            {
                "_index": "dalianpai",
                "_type": "person",
                "_id": "AXFeHQMrEXg1j8gSlZg8",
                "_score": 0.0,
                "_source": {
                    "name": "張三",
                    "age": 20,
                    "mail": "111@qq.com",
                    "hobby": "羽毛球、乒乓球、足球"
                }
            }
        ]
    }
}

查詢和過濾的對比:

  • 一條過濾語句會詢問每個文檔的字段值是否包含着特定值。
  • 查詢語句會詢問每個文檔的字段值與特定值的匹配程度如何。

               一條查詢語句會計算每個文檔與查詢語句的相關性,會給出一個相關性評分 _score,並且 按照相關性對匹配到的文檔進行排序。 這種評分方式非常適用於一個沒有完全配置結果的全文本搜索。

  • 一個簡單的文檔列表,快速匹配運算並存入內存是十分方便的, 每個文檔僅需要1個字節。這些緩存的過濾結果集與后續請求的結合使用是非常高效的。
  • 查詢語句不僅要查找相匹配的文檔,還需要計算每個文檔的相關性,所以一般來說查詢語句要比 過濾語句更耗時,並且查詢結果也不可緩存。

建議:做精確匹配搜索時,最好用過濾語句,因為過濾語句可以緩存數據。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM