2017-08-09 95 views
2

我想在文本的下方列表中搜索單詞藍色春數據彈性搜索通配符搜索

「BlueSaphire」,「Bluo」,「ALUE」,「藍」,「藍」 , 「藍」, 「藍黑色」, 「Bluo」, 「薩費爾藍色」, 「黑」, 「綠色」, 「布盧」, 「Saphireblue」

SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices("color") 
        .withQuery(matchQuery("colorDescriptionCode", "blue") 
        .fuzziness(Fuzziness.ONE) 
       ) 
        .build(); 

這工作得很好,並且搜索結果將以下記錄與分數一起返回

alue 2.8718023 
Bluo 1.7804208 
Bluo 1.7804208 
BLUE 1.2270637 
blue 1.2270637 
Blue 1.2270637 
Blue Black 1.1082436 
Saphire Blue 0.7669148 

但我不能使通配符工作。 「SaphireBlue」和「BlueSaphire」也有望成爲結果的一部分

我試過下面的設置,但它不起作用。

SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices("color") 
         .withQuery(matchQuery("colorDescriptionCode", "(.*?)blue") 
         .fuzziness(Fuzziness.ONE) 
        ) 
         .build(); 

在堆棧溢出中,我觀察到指定分析通配符的解決方案。

QueryBuilder queryBuilder = boolQuery().should(
       queryString("blue").analyzeWildcard(true) 
         .field("colorDescriptionCode", 2.0f); 

我沒有找到queryString靜態方法。我正在使用spring-data-elasticsearch 2.0.0.RELEASE。

讓我知道,這樣藍色也將在搜索返回的結果

+0

您的映射和集羣設置只能幫助正則表達式 – user3775217

+0

您能否詳細說明您的評論?你的意思是在彈性搜索中配置同義詞嗎? – lives

+0

我不知道,那是在那個時候,你不能再以這樣一種違法的方式再問我,直到我得到我非常體面的要求,或者可能在野外飛行時想到我可能已經學會的東西。謝謝 – user3775217

回答

0

我不能在一個查詢實現模糊性和Wilcard搜索包含所有的話,我如何能夠指定的外卡。

這是我可以得到的最接近的解決方案。我必須激發兩個不同的查詢並手動合併結果。

@Query("{\"wildcard\" : {\"colorDescriptionCode\" : \"?0\" }}") 
    Page<ColorDescription> findByWildCard(String colorDescriptionCode, Pageable pageable); 

    @Query("{\"match\": { \"colorDescriptionCode\": { \"query\":  \"?0\", \"fuzziness\": 1 }}}") 
    Page<ColorDescription> findByFuzzy(String colorDescriptionCode, Pageable pageable); 
0

我知道工作的例子總是比理論好,但我仍然想先講一點理論。 Elasticsearch的核心是Lucene。所以在將文檔寫入Lucene索引之前,他會經歷分析階段。分析階段可分爲3部分:

  1. 字符過濾;
  2. 標記化;
  3. 令牌過濾

在第一階段中,我們可以扔掉不必要的字符,例如,HTML標籤。有關字符過濾器的更多信息,請參閱official site。 下一階段更有趣。在這裏,我們將輸入文本分割爲記號,稍後將用於搜索。一些非常有用的tokenizers

  • 標準分詞器。它是默認使用的。標記器實現Unicode文本分段算法。在實踐中,您可以使用它將文本分割成單詞並將這些單詞用作記號。
  • n-gram標記器。如果你想要搜索單詞的一部分,這就是你需要的。該標記器將文本分割爲n個項目的連續序列。例如,文本「例如」將被分割爲這個標記序列"fo", "or", "r ", " e", "ex", "for", "or ex"等.n-gram的長度是可變的,並且可以由min_gram和max_gram params來配置。
  • edge n-gram tokenizer。與n-gram標記器相同,除了一件事情 - 該標記器不增加偏移量。例如,文本「例如」將被分割爲這個標記序列"fo", "for", "for ", "for e", "for ex", "for exa"等。 關於標記器的更多信息可以在官方網站上找到。不幸的是,由於聲譽低下,我無法發佈更多鏈接。

下一個階段也是該死的有趣。在我們將文本分成標記之後,我們可以用這個做很多有趣的事情。我再次給令牌過濾器的一些非常有用的例子:

  • 小寫過濾。在大多數情況下,我們希望得到不區分大小寫的搜索,所以最好將令牌標記爲小寫。
  • 詞幹分析過濾器。當我們與自然語言達成協議時,我們遇到很多問題。其中一個問題是一個詞可以有多種形式。 Stemmer過濾器可以幫助我們獲得單詞的根形式。
  • 模糊濾波器。另一個問題是用戶經常犯錯。此過濾器添加包含可能的拼寫錯誤的標記。

如果你有興趣看分析的結果,你可以使用這個_termvectors端點

curl [ELASTIC_URL]:9200/[INDEX_NAME]/[TYPE_NAME]/[DOCUMENT_ID]/_termvectors?pretty 

現在說說查詢。查詢分爲2個大組。這些組有兩個顯着差異:

  1. 請求是否會通過分析階段;
  2. 是否要求有一個確切的答案(是或否)

例子是匹配查詢和搜索項查詢。第一個將通過分析階段,第二個不會。第一個不會給我們一個具體的答案(但給我們一個分數),第二個會。爲文檔創建映射時,我們可以分別指定分析器的索引和搜索分析器的每個字段。

現在有關彈簧數據elasticsearch的信息。這裏講一些具體的例子很有意義。假設我們有一個帶有標題字段的文檔,我們想要搜索該字段的信息。首先,創建一個包含elasticsearch設置的文件。

{ 
"analysis": { 
    "analyzer": { 
     "ngram_analyzer": { 
      "tokenizer": "ngram_tokenizer", 
      "filter": [ 
       "lowercase" 
      ] 
     }, 
     "edge_ngram_analyzer": { 
      "tokenizer": "edge_ngram_tokenizer", 
      "filter": [ 
       "lowercase" 
      ] 
     }, 
     "english_analyzer": { 
      "tokenizer": "standard", 
      "filter": [ 
       "lowercase", 
       "english_stop", 
       "unique", 
       "english_possessive_stemmer", 
       "english_stemmer" 
      ] 
     "keyword_analyzer": { 
      "tokenizer": "keyword", 
      "filter": ["lowercase"] 
     } 

    }, 
    "tokenizer": { 
     "ngram_tokenizer": { 
      "type": "ngram", 
      "min_gram": 2, 
      "max_gram": 20 
     }, 
     "edge_ngram_tokenizer": { 
      "type": "edge_ngram", 
      "min_gram": 2, 
      "max_gram": 20 
     } 
    }, 
    "filter": { 
     "english_stop": { 
      "type": "stop", 
      "stopwords": "_english_" 
     }, 
    "english_stemmer": { 
     "type": "stemmer", 
     "language": "english" 
    }, 
    "english_possessive_stemmer": { 
     "type": "stemmer", 
     "language": "possessive_english" 
    } 
}  
} 

您可以將此設置保存到您的資源文件夾中。現在讓我們看看我們的文檔類

@Document(indexName = "document", type = "document") 
@Setting(settingPath = "document_index_setting.json") 
public class Document { 

    @Id 
    private String id; 

    @MultiField(
     mainField = @Field(type = FieldType.String, 
          index = not_analyzed), 
     otherFields = { 
       @InnerField(suffix = "edge_ngram", 
         type = FieldType.String, 
         indexAnalyzer = "edge_ngram_analyzer", 
         searchAnalyzer = "keyword_analyzer"), 
       @InnerField(suffix = "ngram", 
         type = FieldType.String, 
         indexAnalyzer = "ngram_analyzer"), 
         searchAnalyzer = "keyword_analyzer"), 
       @InnerField(suffix = "english", 
         type = FieldType.String, 
         indexAnalyzer = "english_analyzer") 
     } 
    ) 
    private String title; 

    // getters and setters omitted 

} 

所以在這裏場冠軍,三個內場:

  • title.edge_ngram由邊緣正克用關鍵詞搜索分析搜索。我們需要這個,因爲我們不需要將我們的查詢分割成邊緣n元組;
  • title.ngram用於n-grams搜索;
  • title.english用於搜索與自然語言的細微差別 和主要字段標題。我們不分析這個,因爲有時候我們想按這個字段排序。 讓我們用簡單的多匹配查詢通過所有這些領域的搜索:
String searchQuery = "blablabla"; 
MultiMatchQueryBuilder queryBuilder = multiMatchQuery(searchQuery) 
    .field("title.edge_ngram", 2) 
    .field("title.ngram") 
    .field("title.english"); 
NativeSearchQueryBuilder searchBuilder = new NativeSearchQueryBuilder() 
    .withIndices("document") 
    .withTypes("document") 
    .withQuery(queryBuilder) 
    .withPageable(new PageRequest(page, pageSize)); 
elasticsearchTemplate.queryForPage(searchBuilder.build, 
            Document.class, 
            new SearchResultMapper() { 
            //realisation omitted }); 

搜索是一個非常有趣的和大量的話題。我試圖儘可能簡短地回答,因爲這可能會導致令人困惑的時刻 - 請不要猶豫。