2013-07-08 13 views
7

Sto cercando di determinare il modo migliore per indicizzare un documento nella ricerca elastica. Ho un documento, Doc, che ha alcuni campi:Come evitare il comportamento di ricerca tra oggetti con tipi nidificati nella ricerca elastica

Doc 
    created_at 
    updated_at 
    field_a 
    field_b 

Ma Doc avrà anche alcuni campi specifici per i singoli utenti. Ad esempio, field_x avrà valore 'A' per l'utente 1 e field_x avrà valore 'B' per l'utente 2. Per ogni documento, ci sarà un numero molto limitato di utenti (in genere 2, fino a ~ 10). Quando un utente cerca su field_x, deve cercare sul valore che gli appartiene. Ho esplorato i tipi annidati in ES.

Doc 
    created_at 
    updated_at 
    field_x: [{ 
    user: 1 
    field_x: A 
    },{ 
    user: 2 
    field_x: B 
    }] 

Quando l'utente 1 ricerca su field_x per il valore 'A', questo documento dovrebbe risultare in un hit Tuttavia, non dovrebbe farlo quando l'utente 1 cerca il valore 'B'.

Tuttavia, according to the docs:

Uno dei problemi durante l'indicizzazione oggetti interni che si verificano diverse volte in un documento è che “oggetto croce” cerca partita si verificherà

Esiste un modo per evitare questo comportamento con tipi nidificati o dovrei esplorare un altro tipo?

Ulteriori informazioni sull'esecuzione di tali richieste sarebbero molto preziose. Solo leggendo i documenti, ha affermato che le query nidificate non sono troppo diverse in termini di prestazioni rispetto alle query regolari. Se qualcuno ha questa esperienza, mi piacerebbe sentirlo.

risposta

5

Il tipo annidato è quello che stai cercando e non preoccuparti troppo delle prestazioni.

Prima di indicizzare i documenti, è necessario impostare la mappatura per i vostri documenti:

curl -XDELETE localhost:9200/index 
curl -XPUT localhost:9200/index 
curl -XPUT localhost:9200/index/type/_mapping -d '{ 
    "type": { 
     "properties": { 
      "field_x": { 
       "type": "nested", 
       "include_in_parent": false, 
       "include_in_root": false, 
       "properties": { 
        "user": { 
         "type": "string" 
        }, 
        "field_x": { 
         "type": "string", 
         "index" : "not_analyzed" // NOTE* 
        } 
       } 
      } 
     } 
    } 
}' 

* Nota: Se il campo contiene in realtà solo lettere singolari come "A" e "B", si don' Voglio analizzare il campo, altrimenti elasticsearch rimuoverà queste "parole" singolari. Se quello era solo il tuo esempio, e nei tuoi documenti reali stai cercando parole appropriate, rimuovi questa riga e lascia che elasticsearch analizzi il campo.

Poi, indice i documenti:

curl -XPUT http://localhost:9200/index/type/1 -d ' 
{ 
    "field_a": "foo", 
    "field_b": "bar", 
    "field_x" : [{ 
     "user" : "1", 
     "field_x" : "A" 
    }, 
    { 
     "user" : "2", 
     "field_x" : "B" 
    }] 
}' 

ed eseguire la query:

curl -XGET localhost:9200/index/type/_search -d '{ 
    "query": { 
     "nested" : { 
      "path" : "field_x", 
      "score_mode" : "avg", 
      "query" : { 
       "bool" : { 
        "must" : [ 
         { 
          "term": { 
           "field_x.user": "1" 
          } 
         }, 
         { 
          "term": { 
           "field_x.field_x": "A" 
          } 
         } 
        ] 
       } 
      } 
     } 
    } 
}'; 

Questo si tradurrà in

{"took":13,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":1,"max_score":1.987628,"hits":[{"_index":"index","_type":"type","_id":"1","_score":1.987628, "_source" : 
{ 
    "field_a": "foo", 
    "field_b": "bar", 
    "field_x" : [{ 
     "user" : "1", 
     "field_x" : "A" 
    }, 
    { 
     "user" : "2", 
     "field_x" : "B" 
    }] 
}}]}} 

Tuttavia, l'interrogazione

curl -XGET localhost:9200/index/type/_search -d '{ 
    "query": { 
     "nested" : { 
      "path" : "field_x", 
      "score_mode" : "avg", 
      "query" : { 
       "bool" : { 
        "must" : [ 
         { 
          "term": { 
           "field_x.user": "1" 
          } 
         }, 
         { 
          "term": { 
           "field_x.field_x": "B" 
          } 
         } 
        ] 
       } 
      } 
     } 
    } 
}'; 

non verrà prodotto risultati

{"took":6,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":0,"max_score":null,"hits":[]}} 
+0

Questa è una grande risposta. Esattamente quello che stavo cercando. Grazie per la tua completezza. – Brad

+0

questa è una vecchia risposta, [vedi documentazione] (https://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-put-mapping.html) per le versioni successive su come l'URL di mappatura è cambiato in 'http: // localhost: 9200/index/_mapping/type'. –

Problemi correlati