2016-12-12 103 views
0

我想提供搜索最終用戶的類型,因爲他們去哪個更像是sqlserver。 我能夠實現ES查詢給定的SQL場景:彈性搜索Wilcard搜索或部分匹配

select * from table where name like '%pete%' and type != 'xyz and type!='abc' 

但對於這個sql查詢

select * from table where name like '%peter tom%' and type != 'xyz and type!='abc' 

的ES查詢不工作在我非常久遠通配符查詢彈性搜索我還需要執行一些布爾過濾查詢

{ 
"query": { 
"filtered": { 
"filter": { 
"bool": { 
"should": [ 
{ 
"query": { 
"wildcard": { 
"name": 
{ "value": "*pete*" } 
} 
} 
} 
], 
"must_not": [ 
{ 
"match": 
{ "type": "xyz" } 
}, { 
"match": 
{ "type": "abc" } 
} 
] 
} 
} 
} 
} 
} 

用通配符搜索上述彈性查詢工作正常,讓我所有的匹配皮特的文件,不是類型XYZ和ABC的。但是,當我嘗試執行與由2個空間seprated seprate詞語通配符那麼相同的查詢返回箱空如圖below.For例如

{ 
    "query": { 
    "filtered": { 
    "filter": { 
    "bool": { 
    "should": [ 
    { 
    "query": { 
    "wildcard": { 
    "name": 
    { "value": "*peter tom*" } 
    } 
    } 
    } 
    ], 
    "must_not": [ 
    { 
    "match": 
    { "type": "xyz" } 
    }, { 
    "match": 
    { "type": "abc" } 
    } 
    ] 
    } 
    } 
    } 
    } 
    } 

我的映射如下:

{ 
    "properties": { 
    "name": { 
     "type": "string" 
    } 
    "type": { 
     "type": "string" 
    } 
    } 
} 

我應該爲了使由空間

+0

您的問題是,你不知道如何ES索引數據。看看這個https://www.elastic.co/guide/en/elasticsearch/guide/current/inverted-index.html。也期待ngGram https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-ngram-tokenizer.html –

+0

所以問題是,當你在ES中編輯文本「hello world」時,它會變成[ 「你好,世界」]。 –

+0

我明白如何將文檔存儲在ES中,但是ES提供了什麼以允許用戶執行sql,如搜索由空格分隔的單詞是我的問題 – andy

回答

2

最有效的解決方案包括利用ngram tokenizer爲了標記name字段的部分內容。舉例來說,如果你有一個像peter tomson一個名稱,NGRAM分詞器將令牌化和指數它是這樣的:

  • PE
  • 寵物
  • 皮特
  • 彼得
  • 彼得牛逼
  • 彼得到
  • 彼得湯姆
  • 彼得湯姆斯
  • 彼得tomso
  • ETER湯臣
  • 之三湯臣
  • 呃湯臣
  • [R湯臣
  • 湯臣
  • 湯臣
  • omson
  • MSON
  • 兒子

所以,當這已被索引,搜索任何這些令牌將檢索您的文檔與peter thomson在其中。

讓我們創建索引:

PUT likequery 
{ 
    "settings": { 
    "analysis": { 
     "analyzer": { 
     "my_ngram_analyzer": { 
      "tokenizer": "my_ngram_tokenizer" 
     } 
     }, 
     "tokenizer": { 
     "my_ngram_tokenizer": { 
      "type": "nGram", 
      "min_gram": "2", 
      "max_gram": "15" 
     } 
     } 
    } 
    }, 
    "mappings": { 
    "typename": { 
     "properties": { 
     "name": { 
      "type": "string", 
      "fields": { 
      "search": { 
       "type": "string", 
       "analyzer": "my_ngram_analyzer" 
      } 
      } 
     }, 
     "type": { 
      "type": "string", 
      "index": "not_analyzed" 
     } 
     } 
    } 
    } 
} 

然後您就可以像這樣來搜索一個簡單的和非常有效的term查詢:

POST likequery/_search 
{ 
    "query": { 
    "bool": { 
     "should": [ 
     { 
      "term": { 
      "name.search": "peter tom" 
      } 
     } 
     ], 
     "must_not": [ 
     { 
      "match": { 
      "type": "xyz" 
      } 
     }, 
     { 
      "match": { 
      "type": "abc" 
      } 
     } 
     ] 
    } 
    } 
} 
+0

感謝您的反饋,你會讓我們知道這兩個屬性的特定:「min_gram」:「2」, 「max_gram」:「15」.is 2表示在這種情況下,maxram是什麼意思。 2.1版本中還有ngram嗎? – andy

+0

'min_gram'是最小字符數(不是單詞),'max_gram'是最大字符數,這意味着這個標記器將對所有可以從您的名稱值創建的長度爲2到15的字符串進行標記和索引。 – Val

+0

好吧,我看到了,謝謝 – andy

1

seprated話通配符搜索可以使用什麼樣的查詢以及我的解決方案是不完美的,我不知道性能。所以,你應該嘗試一下在你自己的風險:)

這是上課

PUT likequery 
{ 
    "mappings": { 
    "typename": { 
     "properties": { 
     "name": { 
      "type": "string", 
      "fields": { 
      "raw": { 
       "type": "keyword" 
      } 
      } 
     }, 
     "type": { 
      "type": "string" 
     } 
     } 
    } 
    } 
} 

5版本ES 2.1的變化「類型」: 「關鍵詞」「類型」: 「串」, 「索引」: 「not_analyzed」

PUT likequery/typename/1 
{ 
    "name": "peter tomson" 
} 

PUT likequery/typename/2 
{ 
    "name": "igor tkachenko" 
} 

PUT likequery/typename/3 
{ 
    "name": "taras shevchenko" 
} 

查詢是情況sensetive

POST likequery/_search 
{ 
    "query": { 
    "regexp": { 
     "name.raw": ".*taras shev.*" 
    } 
    } 
} 

響應

{ 
    "took": 5, 
    "timed_out": false, 
    "_shards": { 
    "total": 5, 
    "successful": 5, 
    "failed": 0 
    }, 
    "hits": { 
    "total": 1, 
    "max_score": 1, 
    "hits": [ 
     { 
     "_index": "likequery", 
     "_type": "typename", 
     "_id": "3", 
     "_score": 1, 
     "fields": { 
      "raw": [ 
      "taras shevchenko" 
      ] 
     } 
     } 
    ] 
    } 
} 

PS。再次我不確定這個查詢的性能,因爲它將使用掃描而不是索引。

+0

謝謝你現在試試 – andy