2012-08-24 11 views
16

diciamo che nel mio indice elasticsearch ho un campo chiamato "punti" che conterrà una stringa di parole separate da punteggiatura (ad esempio "first.second.third").Come abbinare il prefisso in Elasticsearch

Ho bisogno di cercare ad es. "first.second" e quindi ottenere tutte le voci il cui campo "punti" contiene una stringa che è esattamente "first.second" o che inizia con "first.second".

Ho un problema a capire come funziona l'interrogazione del testo, almeno non sono riuscito a creare una query che faccia il lavoro.

risposta

20

elasticsearch ha Path Hierarchy Tokenizer che è stato creato proprio per tale caso d'uso. Ecco un esempio di come deve essere impostato per l'indice:

# Create a new index with custom path_hierarchy analyzer 
# See http://www.elasticsearch.org/guide/reference/index-modules/analysis/pathhierarchy-tokenizer.html 
curl -XPUT "localhost:9200/prefix-test" -d '{ 
    "settings": { 
     "analysis": { 
      "analyzer": { 
       "prefix-test-analyzer": { 
        "type": "custom", 
        "tokenizer": "prefix-test-tokenizer" 
       } 
      }, 
      "tokenizer": { 
       "prefix-test-tokenizer": { 
        "type": "path_hierarchy", 
        "delimiter": "." 
       } 
      } 
     } 
    }, 
    "mappings": { 
     "doc": { 
      "properties": { 
       "dots": { 
        "type": "string", 
        "analyzer": "prefix-test-analyzer", 
        //"index_analyzer": "prefix-test-analyzer", //deprecated 
        "search_analyzer": "keyword" 
       } 
      } 
     } 
    } 
}' 
echo 
# Put some test data 
curl -XPUT "localhost:9200/prefix-test/doc/1" -d '{"dots": "first.second.third"}' 
curl -XPUT "localhost:9200/prefix-test/doc/2" -d '{"dots": "first.second.foo-bar"}' 
curl -XPUT "localhost:9200/prefix-test/doc/3" -d '{"dots": "first.baz.something"}' 
curl -XPOST "localhost:9200/prefix-test/_refresh" 
echo 
# Test searches. 
curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true" -d '{ 
    "query": { 
     "term": { 
      "dots": "first" 
     } 
    } 
}' 
echo 
curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true" -d '{ 
    "query": { 
     "term": { 
      "dots": "first.second" 
     } 
    } 
}' 
echo 
curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true" -d '{ 
    "query": { 
     "term": { 
      "dots": "first.second.foo-bar" 
     } 
    } 
}' 
echo 
curl -XPOST "localhost:9200/prefix-test/doc/_search?pretty=true&q=dots:first.second" 
echo 
+0

Spiacente, non ho visto il tuo messaggio fino ad ora !! Grazie mille :) Lo esaminerò appena avrò il tempo! – Stine

+0

Come si eseguono le impostazioni e le mappature nel mio codice Java? – Stine

+1

'client.admin(). Indices(). PrepareCreate (" test "). AddMapping (" tipo1 ", mapping) .setSettings (settings) .execute(). ActionGet();' – imotov

2

Dai un'occhiata alla prefix queries.

$ curl -XGET 'http://localhost:9200/index/type/_search' -d '{ 
    "query" : { 
     "prefix" : { "dots" : "first.second" } 
    } 
}' 
+1

Non funziona quando la stringa contiene segni di punteggiatura:/ – Stine

+1

[Questo] (https://gist.github.com/3457388) funziona su un nuovo indice.Hai una mappatura speciale sul tuo indice? Forse dovresti provare un nuovo indice pulito. – A21z

+0

Esiste una differenza di efficienza tra l'utilizzo della ricerca prefisso o del tokenizzatore della gerarchia di percorso? –

1

V'è anche un modo molto più semplice, come sottolineato in elasticsearch documentation:

basta usare:

{ 
    "text_phrase_prefix" : { 
     "fieldname" : "yourprefix" 
    } 
} 

o dal 0.19.9:

{ 
    "match_phrase_prefix" : { 
     "fieldname" : "yourprefix" 
    } 
} 

invece di:

{ 
    "prefix" : { 
     "fieldname" : "yourprefix" 
} 
1

Stavo cercando una soluzione simile, ma corrispondente solo a un prefisso. Ho trovato @ imtov di answer per farmi quasi arrivati, ma per un cambiamento - commutazione gli analizzatori in giro:

"mappings": { 
    "doc": { 
     "properties": { 
      "dots": { 
       "type": "string", 
       "analyzer": "keyword", 
       "search_analyzer": "prefix-test-analyzer" 
      } 
     } 
    } 
} 

invece di

"mappings": { 
    "doc": { 
     "properties": { 
      "dots": { 
       "type": "string", 
       "index_analyzer": "prefix-test-analyzer", 
       "search_analyzer": "keyword" 
      } 
     } 
    } 
} 

In questo modo l'aggiunta di:

'{"dots": "first.second"}' 
'{"dots": "first.third"}' 

Aggiungerà solo questi token completi, senza memorizzare i token first, second, third.

Eppure la ricerca di entrambi i

first.second.anyotherstring 
first.second 

restituirà correttamente solo la prima voce:

'{"dots": "first.second"}' 

Non è esattamente quello che hai chiesto, ma in qualche modo legati, così ho pensato potesse aiutare qualcuno.

Problemi correlati