Elasticsearch文檔查詢

来源:http://www.cnblogs.com/ginb/archive/2017/06/13/7000427.html
-Advertisement-
Play Games

Elasticsearch快速入門 第1篇:Elasticsearch入門 Elasticsearch快速入門 第2篇:Elasticsearch和Kibana安裝 Elasticsearch快速入門 第3篇:Elasticsearch索引和文檔操作 Elasticsearch快速入門 第4篇:El ...


簡單數據集

到目前為止,已經瞭解了基本知識,現在我們嘗試用更逼真的數據集,這兒已經準備好了一份虛構的JSON,關於客戶銀行賬戶信息的。每個文檔的結構如下:

{
    "account_number": 0,
    "balance": 16623,
    "firstname": "Bradshaw",
    "lastname": "Mckenzie",
    "age": 29,
    "gender": "F",
    "address": "244 Columbus Place",
    "employer": "Euron",
    "email": "[email protected]",
    "city": "Hobucken",
    "state": "CO"
}

出於好奇,我從www.json-generator.com/生成了這些數據,請忽略數據的實際值和語義,因為這些都是隨機生成的。

載入樣本數據集

可以從這裡下載示例數據集(accounts.json),解壓到當前目錄,然後用以下方式把它載入到集群中

curl -H "Content-Type: application/json" -XPOST 'localhost:9200/bank/account/_bulk?pretty&refresh' --data-binary "@accounts.json"
curl 'localhost:9200/_cat/indices?v'

返回內容如下:

health status index   uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   .kibana XYZPR5XGQGWj8YlyZ1et_w   1   1          1            0      3.1kb          3.1kb
yellow open   bank    uoTQIb3GSDOH08CmsIy66A   5   1        999            0    639.5kb        639.5kb

這意味著我們已經成功批量索引999個文檔到bank索引下(類型為account )。

註意,上面的操作不能在kibana中執行,需要使用curl

具體操作是,把下載的json文檔放在和curl.exe相同的目錄,然後打開命令提示符定位到curl.exe所在目錄,然後粘貼以下命令(我的curl版本是7.53.1,需要改成下麵的方式才能執行成功),回車即可

curl -H "Content-Type: application/json" -XPOST localhost:9200/bank/account/_bulk?pretty --data-binary "@accounts.json"

查詢API

運行查詢有兩種方式,一是通過 REST request URI 方式發送查詢參數,二是通過 REST request body 。方式二更為靈活,可以使用可讀性好的JSON 格式定義你的查詢條件,下麵我們針對方式一舉個例子,以後的教程都使用方式二。

REST API查詢條件放在_search之後,以下例子返回 bank 索引中的所有文檔:

GET /bank/_search?q=*&sort=account_number:asc&pretty
bank 表示查詢bank索引中的文檔, _search 後面跟的是查詢條件,q=* 參數指示 Elasticsearch 匹配索引中的所有文檔。 sort=account_number:asc 參數指示使用 account_number 對結果進行升序排序。 pretty 參數告訴 Elasticsearch 返回漂亮的JSON結果。

返回部分內容如下:

{
  "took" : 63,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : null,
    "hits" : [ {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "0",
      "sort": [0],
      "_score" : null,
      "_source" : {"account_number":0,"balance":16623,"firstname":"Bradshaw","lastname":"Mckenzie","age":29,"gender":"F","address":"244 Columbus Place","employer":"Euron","email":"[email protected]","city":"Hobucken","state":"CO"}
    }, {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "1",
      "sort": [1],
      "_score" : null,
      "_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"[email protected]","city":"Brogan","state":"IL"}
    }, ...
    ]
  }
}

至於返回內容,我們看到以下部分:

  • took -  Elasticsearch  執行查詢的時間(以毫秒為單位)
  • timed_out - 告訴我們查詢是否超時
  • _shards - 告訴我們查詢了多少個分片,以及查詢成功/失敗的分片數量
  • hits - 查詢結果
  • hits.total - 符合我們查詢條件的文檔總數
  • hits.hits - 實際查詢結果數組(預設為前10個文檔)
  • hits.sort - 對結果進行排序的鍵(如果沒提供,則預設使用_score進行排序)
  • hits._scoremax_score-現在先忽略這些欄位

使用方式二執行上面查詢如下

GET /bank/_search
{
  "query": { "match_all": {} },
  "sort": [
    { "account_number": "asc" }
  ]
}

不同點是我們用json格式的請求體代替了_search api uri中的q=*參數。我們將會在後面的內容討論json格式的查詢。

註意,當我們接收到返回結果的時候, elasticsearch 已經完全處理了這個請求,不會維護任何的伺服器端的資源或者在結果中打開游標。這與許多其他的平臺形成鮮明的對比(比如sql的游標)

查詢語言介紹

 Elasticsearch  t提供了一種 JSON-style 的特定領域語言用來執行查詢,稱為 Query DSL,該查詢語言十分全面,初看可能覺得有點嚇人。事實上,學習它的最好方式就是從幾個基本的例子開始。回到上一個例子,我們執行了這個查詢:

GET /bank/_search
{
  "query": { "match_all": {} }
}

上面的 query   部分告訴我們查詢定義是什麼,  match_all 部分僅僅是我們想運行的查詢的類型,也就是查詢指定索引下的所有文檔。

除了查詢參數以外,也可以通過其他參數影響查詢結果。比如前面的 sort 指定排序欄位,下麵通過 size 指定返回結果數

GET /bank/_search
{
  "query": { "match_all": {} },
  "size": 1
}

註意 size 如果不指定,預設是10。

下麵的例子匹配所有,並且返回第11到20之間的文檔

GET /bank/_search
{
  "query": { "match_all": {} },
  "from": 10,
  "size": 10
}

 from參數(最小值是0,不是1)指定返迴文檔的起始文檔的索引, size 參數指定一共返回多少個文檔。這個特性對實現分頁非常有用。如果 from 沒有指定,預設值是0。

下麵的例子匹配所有,並且通過 balance 欄位對結果進行降序排序,返回前10條(預設 size )文檔。

GET /bank/_search
{
  "query": { "match_all": {} },
  "sort": { "balance": { "order": "desc" } }
}

執行查詢

接下來我們進一步探討Query DSL。首先看一下返回的文檔欄位。預設情況下,完整的JSON文檔作為所有搜索的一部分返回。

預設情況下,完整的JSON文檔作為所有搜索的一部分返回。文檔原始內容被稱為源(查詢結果中的_source欄位)。如果不希望返回整個源文檔,也可以請求僅幾個欄位被返回。

以下示例顯示如何返回兩個欄位(_source內), account_number  balance

GET /bank/_search
{
  "query": { "match_all": {} },
  "_source": ["account_number", "balance"],
  "size": 1
  
}

返回內容如下:

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 999,
    "max_score": 1,
    "hits": [
      {
        "_index": "bank",
        "_type": "account",
        "_id": "25",
        "_score": 1,
        "_source": {
          "account_number": 25,
          "balance": 40540
        }
      }
    ]
  }
}

以上的例子僅僅減少了 _source 里的欄位,返回的欄位 account_number 和 balance 仍然包含在 _source

如果你之前有SQL背景,上述在概念上與SQL SELECT FROM欄位列表有些相似。

現在來看看查詢部分。通過前面的示例,我們已經學會瞭如何使用 match_all 查詢來匹配所有文檔。現在介紹一個名為match查詢的新查詢,可以將其視為基本的欄位搜索查詢(即針對特定欄位或一組欄位進行搜索)。

以下示例返回的 account_number 為20:

GET /bank/_search
{
  "query": { "match": { "account_number": 20 } }
}

返回結果:

{
  "took": 15,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "bank",
        "_type": "account",
        "_id": "20",
        "_score": 1,
        "_source": {
          "account_number": 20,
          "balance": 16418,
          "firstname": "Elinor",
          "lastname": "Ratliff",
          "age": 36,
          "gender": "M",
          "address": "282 Kings Place",
          "employer": "Scentric",
          "email": "[email protected]",
          "city": "Ribera",
          "state": "WA"
        }
      }
    ]
  }
}

以下實例返回 address 中包含"mill"的所有賬戶:

GET /bank/_search
{
  "query": { "match": { "address": "mill" } }
}

以下示例返回address中包含"mill"或者"lane"的所有賬戶:

GET /bank/_search
{
  "query": { "match": { "address": "mill lane" } }
}

以下示例是matchmatch_phrase)的一個變體,返回在地址中包含短語"mill lane"的所有帳戶:

GET /bank/_search
{
  "query": { "match_phrase": { "address": "mill lane" } }
}

下麵介紹bool(ean) query 布爾查詢允許我們把多個 match 查詢合併到一個查詢中。

以下示例由兩個 match  查詢組成,返回 address 中既包含"mill" 又包含"lane" 的所有賬戶:

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}

在上面的示例中, bool must 裡面的所有查詢條件必須都為真時才會被匹配。

相比之下,下麵的示例由兩個match查詢組成,並返回在地址中包含"mill"或"lane"的所有帳戶:

GET /bank/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}

在上面的例子中, bool should 子句指定了一個查詢列表,只要其中一個查詢為真,文檔就會被匹配。

以下示例由兩個match查詢組成,並返回在地址中既不包含"mill"也不包含"lane"的所有帳戶:

GET /bank/_search
{
  "query": {
    "bool": {
      "must_not": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}

在上面的例子中,bool must_not 子句指定一個查詢列表,只有查詢列表中的條件都為假的時候才會被匹配。

也可以把 must,should,must_not 同時組合到bool子句。此外,我們也可以組合bool 到任何一個bool子句中,實現複雜的多層bool子句嵌套邏輯。

下麵的例子返回所有年齡是40歲但不居住在ID(Idaho)的賬戶:

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "age": "40" } }
      ],
      "must_not": [
        { "match": { "state": "ID" } }
      ]
    }
  }
}

執行過濾

前面我們跳過了一點細節,文檔得分(也就是在搜索結果中的 _score 欄位)。分數是一個數值,它是文檔與我們指定的搜索查詢匹配的相對度量。分數越高,文檔越相關,分數越低,文檔的相關性越低。但查詢並不總是需要產生分數,特別是當它們僅用於"過濾"文檔集時。 Elasticsearch 會檢測這些情況,並自動優化查詢執行,以免計算無用的分數。

bool查詢支持filter子句,它允許你使用一個查詢語句去限制其它子句的匹配結果,同時不會計算文檔的得分。例如,我們來介紹一下 range query, 它允許我們通過一個範圍值去過濾文檔。通常用於數字或日期過濾。

以下示例使用布爾查詢返回餘額在20000到30000之間(包括端值)的所有帳戶。換句話說,我們想找到餘額大於或等於20000且小於等於30000的賬戶。

GET /bank/_search
{
  "query": {
    "bool": {
      "must": { "match_all": {} },
      "filter": {
        "range": {
          "balance": {
            "gte": 20000,
            "lte": 30000
          }
        }
      }
    }
  }
}

仔細分析上面的例子,bool查詢包含了一個match_all查詢(查詢部分)和一個range查詢(過濾部分)。我們也可以用任何其它的查詢語句代替查詢和過濾部分的語句。對於上面的例子,因為所有文檔都是指定範圍之內的,他們從某種意義上來說是等價的(equally),即他們的相關度都是一樣的(filter子句查詢,不會改變得分)。

除了 match_all,match,bool,range查詢,還有很多種類的查詢,但我們不在這裡一一介紹。從現在開始,我們對查詢已經有一個基礎的瞭解,把學到的知識應用到其他查詢類型應該也沒什麼難度。

執行聚合

聚合提供從數據中分組和提取統計信息的功能。理解聚合的最簡單的方法是將其大致等同於SQL GROUP BY和SQL聚合函數。在 Elasticsearch 中,可以返回匹配搜索的同時返回聚合結果,在一個響應中將所有匹配的結果和聚合結果同時返回。這是非常強大和高效的,可以降低網路請求的次數。

以下示例通過state欄位進行分組,並按照count 降序排序,返回前10(預設值)條數據:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword"
      }
    }
  }
}

在SQL中,上述聚合在概念上類似於:

SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC

返回內容(僅部分)如下:

{
  "took": 50,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 999,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "group_by_state": {
      "doc_count_error_upper_bound": 20,
      "sum_other_doc_count": 770,
      "buckets": [
        {
          "key": "ID",
          "doc_count": 27
        },
        {
          "key": "TX",
          "doc_count": 27
        },
        {
          "key": "AL",
          "doc_count": 25
        },
        {
          "key": "MD",
          "doc_count": 25
        },
        {
          "key": "TN",
          "doc_count": 23
        },
        {
          "key": "MA",
          "doc_count": 21
        },
        {
          "	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、創建通知,最好在viewDidLoad的方法中創建 2、發送通知 3、移除通知,由那個控制器創建由那個控制器移除,誰創建誰移除,最好在dealloc方法中移除,如果通知不能及時的移除掉,當下次進入該控制器時會重覆創建NSNotificationCenter,在對應方法中發送通知給上一次創建的通知 ...
  • 多線程是程式開發中非常基礎的一個概念,大家在開發過程中應該或多或少用過相關的東西。同時這恰恰又是一個比較棘手的概念,一切跟多線程掛鉤的東西都會變得複雜。如果使用過程中對多線程不夠熟悉,很可能會埋下一些難以預料的坑。 iOS中的多線程技術主要有NSThread, GCD和NSOperation。他們的 ...
  • 今天博客中,我們就來實現一下一些常用資訊類App中常用的分類選擇的控制項的封裝。本篇博客中沒有使用到什麼新的技術點,如果非得說用到了什麼新的技術點的話,那麼勉強的說,用到了一些iOS9以後UICollectionView添加的一些新的特性。本篇博客所涉及的技術點主要有UICollectionView的 ...
  • 一、官網關於SQL SERVER Browser服務的解釋(谷歌翻譯後稍作修改的): https://docs.microsoft.com/en-us/sql/tools/configuration-manager/sql-server-browser-service 背景: 在SQL Server ...
  • 本文出處:http://www.cnblogs.com/wy123/p/7003157.html 最近無意間看到一個MySQL分頁優化的測試案例,並沒有非常具體地說明測試場景的情況下,給出了一種經典的方案,因為現實中很多情況都不是固定不變的,能總結出來通用性的做法或者說是規律,是要考慮非常多的場景的 ...
  • 標簽:MSSQL/只讀路由 概述 Alwayson相對於資料庫鏡像最大的優勢就是可讀副本,帶來可讀副本的同時還添加了一個新的功能就是配置只讀路由實現讀寫分離;當然這裡的讀寫分離稍微誇張了一點,只能稱之為半讀寫分離吧!看接下來的文章就知道為什麼稱之為半讀寫分離。 db01:192.168.1.22 d ...
  • 線性回歸演算法,是利用數理統計中回歸分析,來確定兩種或兩種以上變數間相互依賴的定量關係的一種統計分析方法。 1. 梯度下降法 線性回歸可以使用最小二乘法,但是速度比較慢,因此一般使用梯度下降法(Gradient Descent),梯度下降法又分為批量梯度下降法(Batch Gradient Desce ...
  • 目錄 一、pymysql 二、SQLAlchemy 一、pymysql pymsql是Python中操作MySQL的模塊,其使用方法和MySQLdb幾乎相同。 1. 下載安裝 2. 使用操作 a. 執行SQL b. 獲取新創建數據自增ID c. 獲取查詢數據 註:在fetch數據時按照順序進行,可以 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...