2015-02-23 18 views
7

Sto creando un motore di ricerca di prodotto con Elastic Search nella mia applicazione .NET, utilizzando il client NEST, e c'è una cosa con cui ho problemi. Ottenere un insieme distinto di valori.Ottenere valori distinti utilizzando il client NAST ElasticSearch

Sono alla ricerca di prodotti, che ci sono molte migliaia, ma ovviamente posso solo restituire 10 o 20 alla volta per l'utente. E per questo cercapersone funziona bene. Ma oltre a questo risultato primario, voglio mostrare ai miei utenti un elenco di marchi che si trovano all'interno della ricerca completa, per presentarli per il filtraggio.

Ho letto a tale proposito che dovrei usare i termini Aggregazioni per questo. Ma non potrei ottenere niente di meglio di questo. E questo ancora non mi dà veramente quello che voglio, perché divide valori come "20th Century Fox" in 3 valori separati.

var brandResults = client.Search<Product>(s => s 
     .Query(query) 
     .Aggregations(a => a.Terms("my_terms_agg", t => t.Field(p => p.BrandName).Size(250)) 
     ) 
    ); 

    var agg = brandResult.Aggs.Terms("my_terms_agg"); 

È questo l'approccio giusto? O dovrebbe usare qualcosa di completamente diverso? E come posso ottenere i valori corretti e completi? (Non diviso dallo spazio .. ma immagino che sia quello che ottieni quando chiedi una lista di "Termini" ??)

Quello che sto cercando è quello che otterresti se lo facessi in MS SQL

SELECT DISTINCT BrandName FROM [Table To Search] WHERE [Where clause without paging] 

risposta

4

È corretto che ciò che si desidera sia un'aggregazione dei termini. Il problema che stai incontrando è che ES sta dividendo il campo "BrandName" nei risultati che sta restituendo. Questo è il comportamento predefinito previsto di un campo in ES.

Quello che consiglio è di cambiare BrandName in un "Multifield", questo ti permetterà di cercare su tutte le varie parti, oltre a fare un'aggregazione dei termini sul "20th Century Fox" non analizzato ") termine.

Questa è la documentazione di ES.

https://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/mapping-multi-field-type.html

[UPDATE] Se si utilizza ES versione 1.4 o più recente la sintassi per il multi-campi è un po 'diverso ora.

https://www.elasticsearch.org/guide/en/elasticsearch/reference/current/_multi_fields.html#_multi_fields

Ecco un esempio di lavoro completa il illustrano il punto in ES 1.4.4. Nota la mappatura specifica una versione "not_analyzed" del campo.

PUT hilden1 

PUT hilden1/type1/_mapping 
{ 
    "properties": { 
    "brandName": { 
     "type": "string", 
     "fields": { 
     "raw": { 
      "type": "string", 
      "index": "not_analyzed" 
     } 
     } 
    } 
    } 
} 

POST hilden1/type1 
{ 
    "brandName": "foo" 
} 

POST hilden1/type1 
{ 
    "brandName": "bar" 
} 

POST hilden1/type1 
{ 
    "brandName": "20th Century Fox" 
} 

POST hilden1/type1 
{ 
    "brandName": "20th Century Fox" 
} 

POST hilden1/type1 
{ 
    "brandName": "foo bar" 
} 

GET hilden1/type1/_search 
{ 
    "size": 0, 
    "aggs": { 
    "analyzed_field": { 
     "terms": { 
     "field": "brandName", 
     "size": 10 
     } 
    }, 
    "non_analyzed_field": { 
     "terms": { 
     "field": "brandName.raw", 
     "size": 10 
     } 
    }  
    } 
} 

risultati dell'ultima query:

{ 
    "took": 3, 
    "timed_out": false, 
    "_shards": { 
     "total": 5, 
     "successful": 5, 
     "failed": 0 
    }, 
    "hits": { 
     "total": 5, 
     "max_score": 0, 
     "hits": [] 
    }, 
    "aggregations": { 
     "non_analyzed_field": { 
     "doc_count_error_upper_bound": 0, 
     "sum_other_doc_count": 0, 
     "buckets": [ 
      { 
       "key": "20th Century Fox", 
       "doc_count": 2 
      }, 
      { 
       "key": "bar", 
       "doc_count": 1 
      }, 
      { 
       "key": "foo", 
       "doc_count": 1 
      }, 
      { 
       "key": "foo bar", 
       "doc_count": 1 
      } 
     ] 
     }, 
     "analyzed_field": { 
     "doc_count_error_upper_bound": 0, 
     "sum_other_doc_count": 0, 
     "buckets": [ 
      { 
       "key": "20th", 
       "doc_count": 2 
      }, 
      { 
       "key": "bar", 
       "doc_count": 2 
      }, 
      { 
       "key": "century", 
       "doc_count": 2 
      }, 
      { 
       "key": "foo", 
       "doc_count": 2 
      }, 
      { 
       "key": "fox", 
       "doc_count": 2 
      } 
     ] 
     } 
    } 
} 

notare che i campi non-analizzati mantengono "volpe del 20 ° secolo" e "foo bar" insieme dove come il campo di analisi li rompe.

+0

Ho appena iniziato con questo una settimana fa. Quindi sto lavorando alla versione 1.4.4 più recente. – Bart

+0

Cosa intendi cambiando il BrandName. Aggiornamento dello schema del database? O modificalo in linea, nella mia domanda? – Bart

+0

Modificare l'indicizzatore ES (database). – jhilden

1

Ho avuto un problema simile. Stavo visualizzando i risultati della ricerca e volevo mostrare i conteggi sulla categoria e sottocategoria.

Hai ragione di utilizzare le aggregazioni. Ho anche avuto il problema che le stringhe venissero troncate (cioè la volpe del XX secolo era divisa) - questo succede perché i campi sono analizzati. Per quanto mi riguarda, ho aggiunto le seguenti mappature (cioè dicono ES non analizzare quel campo):

"category": { 
      "type": "nested", 
      "properties": { 
      "CategoryNameAndSlug": { 
       "type": "string", 
       "index": "not_analyzed" 
      }, 
      "SubCategoryNameAndSlug": { 
       "type": "string", 
       "index": "not_analyzed" 
      } 
      } 
     } 

Come jhilden suggerito, se si utilizza questo campo per più di un motivo (ad esempio,ricerca e aggregazione) è possibile configurarlo come un multi-campo. Quindi da una parte può essere analizzato e utilizzato per la ricerca e dall'altra parte per non essere analizzato per l'aggregazione.

+0

Già, questo è chiaro allora. Grazie per le informazioni! – Bart

+0

Che aspetto ha la query distinta e di conteggio? Sembra interessante da guardare. – Bart

Problemi correlati