[英]How to Query elasticsearch index with nested and non nested fields
我有一個具有以下映射的彈性搜索索引:
PUT /student_detail
{
"mappings" : {
"properties" : {
"id" : { "type" : "long" },
"name" : { "type" : "text" },
"email" : { "type" : "text" },
"age" : { "type" : "text" },
"status" : { "type" : "text" },
"tests":{ "type" : "nested" }
}
}
}
存儲的數據格式如下:
{
"id": 123,
"name": "Schwarb",
"email": "abc@gmail.com",
"status": "current",
"age": 14,
"tests": [
{
"test_id": 587,
"test_score": 10
},
{
"test_id": 588,
"test_score": 6
}
]
}
我希望能夠查詢學生的名字像'%warb%'和email像'%gmail.com%'並且ID為587的測試得分> 5等。需要的高水平可以像這樣下面,不知道實際的查詢是什么,為下面這個混亂的查詢道歉
GET developer_search/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "abc"
}
},
{
"nested": {
"path": "tests",
"query": {
"bool": {
"must": [
{
"term": {
"tests.test_id": IN [587]
}
},
{
"term": {
"tests.test_score": >= some value
}
}
]
}
}
}
}
]
}
}
}
查詢必須靈活,以便我們可以輸入動態測試 ID 及其各自的分數過濾器以及嵌套字段之外的字段,例如年齡、姓名、狀態
類似的東西?
GET student_detail/_search
{
"query": {
"bool": {
"must": [
{
"wildcard": {
"name": {
"value": "*warb*"
}
}
},
{
"wildcard": {
"email": {
"value": "*gmail.com*"
}
}
},
{
"nested": {
"path": "tests",
"query": {
"bool": {
"must": [
{
"term": {
"tests.test_id": 587
}
},
{
"range": {
"tests.test_score": {
"gte": 5
}
}
}
]
}
},
"inner_hits": {}
}
}
]
}
}
}
內部打擊是您正在尋找的。
您必須使用Ngram Tokenizer ,因為出於性能原因,不得使用通配符搜索,我不建議使用它。
將您的映射更改為下面,您可以在下面的映射中創建您自己的分析器。
elasticsearch(albiet lucene)如何索引語句是,首先它將語句或段落分解為單詞或標記,然后在該特定字段的倒排索引中索引這些單詞。 此過程稱為分析,僅適用於text
數據類型。
因此,現在您只有在這些標記在倒排索引中可用時才能獲得文檔。
默認情況下,將應用標准分析器。 我所做的是創建了自己的分析器並使用了 Ngram Tokenizer,它可以創建更多的標記,而不僅僅是單詞。
Life is beautiful
默認分析儀將是life
, is
, beautiful
。
但是使用 Ngrams, Life
的標記將是lif
、 ife
和life
PUT student_detail
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "ngram",
"min_gram": 3,
"max_gram": 4,
"token_chars": [
"letter",
"digit"
]
}
}
}
},
"mappings" : {
"properties" : {
"id" : {
"type" : "long"
},
"name" : {
"type" : "text",
"analyzer": "my_analyzer",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"email" : {
"type" : "text",
"analyzer": "my_analyzer",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"age" : {
"type" : "text" <--- I am not sure why this is text. Change it to long or int. Would leave this to you
},
"status" : {
"type" : "text",
"analyzer": "my_analyzer",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"tests":{
"type" : "nested"
}
}
}
}
請注意,在上面的映射中,我以name
、 email
和status
的關鍵字形式創建了一個兄弟字段,如下所示:
"name":{
"type":"text",
"analyzer":"my_analyzer",
"fields":{
"keyword":{
"type":"keyword"
}
}
}
現在您的查詢可以像下面這樣簡單。
POST student_detail/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "war" <---- Note this. This would even return documents having "Schwarb"
}
},
{
"match": {
"email": "gmail" <---- Note this
}
},
{
"nested": {
"path": "tests",
"query": {
"bool": {
"must": [
{
"term": {
"tests.test_id": 587
}
},
{
"range": {
"tests.test_score": {
"gte": 5
}
}
}
]
}
}
}
}
]
}
}
}
請注意,對於完全匹配,我將在關鍵字字段上使用術語查詢,而對於SQL
中的正常搜索或LIKE
,我將在文本字段上使用簡單的匹配查詢,前提是它們使用Ngram Tokenizer
。
另請注意,對於>=
和<=
您將需要使用Range Query 。
{
"took" : 233,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 3.7260926,
"hits" : [
{
"_index" : "student_detail",
"_type" : "_doc",
"_id" : "1",
"_score" : 3.7260926,
"_source" : {
"id" : 123,
"name" : "Schwarb",
"email" : "abc@gmail.com",
"status" : "current",
"age" : 14,
"tests" : [
{
"test_id" : 587,
"test_score" : 10
},
{
"test_id" : 588,
"test_score" : 6
}
]
}
}
]
}
}
請注意,我在運行查詢時的回復中觀察到您在問題中提到的文檔。
請閱讀我分享的鏈接。 了解這些概念至關重要。 希望這可以幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.