2016-03-02 81 views
4

對於ElasticSearch查詢,我們希望以不同的方式處理單詞(即令牌只包含字母)和非單詞。爲此,我們嘗試定義兩個分析器,要麼返回單詞,要麼返回非單詞。如何根據ElasticSearch中的正則表達式過濾令牌

例如,我們有一個描述產品的硬件存儲文檔:

{ 
    "name": "Torx drive T9", 
    "category": "screws", 
    "size": 2.5, 
} 

然後用戶會搜索「梅花T9」,並期望找到這個文件。搜索T9會過於通用,並會提供太多不相關的產品。因此,如果我們已經找到'Torx',我們只想搜索'T9'術語。

我們努力創建這樣

{ 
    "query": { 
     "bool": { 
      "must": { 
       "match: { 
        "name": { 
        "query": "Torx T9", 
        "analyzer": "words" 
       } 
      }, 
      "should": { 
       "match: { 
        "name": { 
        "query": "Torx T9", 
        "analyzer": "nonwords" 
       } 
      } 
     } 
    } 
} 

的想法是,這將是簡單的創建令牌過濾器來做到這一點的查詢。例如:

"settings": { 
    "analysis": { 
    "filter": { 
     "words": { 
      "type": "pattern", 
      "pattern": "\\A\\p{L}*\\Z", 
     }, 
     "nonwords": { 
      "type": "pattern", 
      "pattern": "\\P{L}", 
     } 
    } 
} 

但似乎沒有過濾器只匹配模式。相反,我們(AB)使用pattern_replace過濾器:

"settings": { 
    "analysis": { 
    "filter": { 
     "words": { 
      "type": "pattern_replace", 
      "pattern": "\\A((?=.*\\P{L}).*)", 
      "replacement": "" 
     }, 
     "nonwords": { 
      "type": "pattern_replace", 
      "pattern": "\\A((?!.*\\P{L}).*)", 
      "replacement": "" 
     }, 
     "nonempty": { 
      "type": "length", 
      "min":1 
     } 
    } 
} 

這與空的令牌,然後可以通過非空過濾除去取代不必要的令牌。這似乎工作,但所需的模式更晦澀。

有沒有更好的表達方式?

+0

您是否還可以顯示一個或兩個示例文檔,並說明您想匹配的分別不匹配? – Val

+0

也許另一個想法是使用[平板標記過濾器](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-shingle-tokenfilter.html)來將單詞索引在一起,所以'T9'永遠不會被單獨索引,從而不能單獨搜索。仍然在尋找一種洗牌方式,這樣,您可以將它與索引牌過濾器一起編入索引:「torx驅動器」,「torx t9」,「驅動器t9」。我也在尋找[短語建議者](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-phrase.html),這可能會提供一種方法來實現這一點。 – Val

+1

我喜歡你提出的方法。如果過濾功能太笨重,只需將您的單詞和非單詞作爲索引器的一部分(ES外部)分隔到不同的字段中即可。 –

回答

1

對於您的需求,您可以使用default_operator作爲「AND」來嘗試query-string-query

例如,考慮你是索引兩個字符串「梅花驅動器T9」和「廣場驅動器T9」。如果您使用whitespace tokenizer索引,則字符串將被分析爲以下標記

第一個文檔:torxdrivet9
第二份文件:square,drivet9

然後使用查詢字符串查詢將文檔與默認運算符匹配爲AND將產生預期結果。

示例映射

{ 
    "settings": { 
    "analysis": { 
     "analyzer": { 
     "whitespace": { 
      "type": "pattern", 
      "pattern": "\\s+" 
     } 
     } 
    } 
    }, 
    "mappings": { 
    "my_type": { 
     "properties": { 
     "name": { 
      "type": "string", 
      "analyzer": "whitespace" 
     } 
     } 
    } 
    } 
} 

示例查詢

{ 
    "query": { 
    "query_string": { 
     "default_field": "name", 
     "query": "Torx T9", 
     "default_operator": "AND" 
     } 
    } 
} 

這個查詢會產生結果,只有當torxt9呈現在文檔中。

+0

如果您只請求't9',會發生什麼情況?您還會得到結果嗎?我認爲這正是@pmakholm想要避免的。 – Val

+0

查詢t9也會產生結果,但我認爲最好讓用戶選擇't9'或'torx t9'。如果查詢t9應該被嚴格避免,那麼可以在查詢客戶端或java中的彈性搜索之前完成。如果它應該在彈性搜索中完成,那麼我希望最好使用[shringles](https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-shingle-tokenfilter.html)在評論中提到。 –