2013-05-23 14 views
10

Ricerca di nomi (testo) con spazi in esso, causando problema per me, devo mappatura simile aCerca nome (testo) con spazi in elasticsearch

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

Idealmente quello che dovrebbe tornare e risultati di rango come segue

1) Bring on top names that exact match the search term (highest score) 
2) Names that starts with the search term (high score) 
3) Names that contains the exact search term as substring (medium score) 
4) Names that contains any of the search term token (lowest score) 

Esempio Per le seguenti nomi in elasticsearch

Maaz Tariq 
Ahmed Maaz Tariq 
Maaz Sheeba 
Maaz Bin Tariq 
Sana Tariq 
Maaz Tariq Ahmed 

Ricerca di "Maaz Tariq", I risultati devono essere in ordine

Maaz Tariq (highest score) 
Maaz Tariq Ahmed (high score) 
Ahmed Maaz Tariq (medium score) 
Maaz Bin Tariq (lowest score) 
Maaz Sheeba (lowest score) 
Sana Tariq (lowest score) 

Può qualunque punto me come e quali analizzatori da utilizzare in seguito? e come classificare i risultati della ricerca per i nomi?

risposta

8

È possibile utilizzare multi field type, un bool query e custom boost factor query per risolvere questo problema.

Mapping:

{ 
    "mappings" : { 
     "user" : {   
      "properties" : { 
       "name": { 
        "type": "multi_field", 
        "fields": { 
         "name": { "type" : "string", "index": "analyzed" }, 
         "exact": { "type" : "string", "index": "not_analyzed" } 
        } 
       } 
      } 
     } 
    } 
} 

Query:

{ 
    "query": { 
     "bool": { 
      "must": [ 
       { 
        "match": { 
         "name": "Maaz Tariq" 
        } 
       } 
      ], 
      "should": [ 
       { 
        "custom_boost_factor": { 
         "query": { 
          "term": { 
           "name.exact": "Maaz Tariq" 
          } 
         }, 
         "boost_factor": 15 
        } 
       }, 
       { 
        "custom_boost_factor": { 
         "query": { 
          "prefix": { 
           "name.exact": "Maaz Tariq" 
          } 
         }, 
         "boost_factor": 10 
        } 
       }, 
       { 
        "custom_boost_factor": { 
         "query": { 
          "match_phrase": { 
           "name": { 
            "query": "Maaz Tariq", 
            "slop": 0 
           } 
          } 
         }, 
         "boost_factor": 5 
        } 
       } 
      ] 
     } 
    } 
} 

edit:

Come sottolineato da javanna, il custom_boost_factor non è necessaria.

query senza custom_boost_factor:

{ 
    "query": { 
     "bool": { 
      "must": [ 
       { 
        "match": { 
         "name": "Maaz Tariq" 
        } 
       } 
      ], 
      "should": [ 
       { 
        "term": { 
         "name.exact": { 
          "value": "Maaz Tariq", 
          "boost": 15 
         } 
        } 
       }, 
       { 
        "prefix": { 
         "name.exact": { 
          "value": "Maaz Tariq", 
          "boost": 10 
         } 
        } 
       }, 
       { 
        "match_phrase": { 
         "name": { 
          "query": "Maaz Tariq", 
          "slop": 0, 
          "boost": 5 
         } 
        } 
       } 
      ] 
     } 
    } 
} 
+0

lo farei preferire una soluzione basata su filtri ma non ho trovato il filtro giusto per il 3. requisito. – Ivaldi

+0

È sufficiente creare una query a frase. Inoltre, non capisco perché hai bisogno di una query custom_boost_factor. Non puoi semplicemente dare un peso diverso alle tue diverse query usando l'opzione 'boost'? – javanna

+0

'Boost' non è consentito in una sub query' should' !? (Almeno non conosco la sintassi per questo.) E come funziona un filtro di query frase senza la query 'span_near' e senza la query' match_phrase'? – Ivaldi

0

In caso di Java Api, quando quering stringhe esatte con spazi usare;

CLIENT.prepareSearch(index) 
    .setQuery(QueryBuilders.queryStringQuery(wordString) 
    .field(fieldName)); 

In un sacco di altre query, si ottiene nulla come risultato