2014-09-22 1 views
2

que je veux faire une requête générique pour QNMZ-1900ElasticSearch requête générique avec des traits d'union et filtre de minuscules

Comme je l'ai lu dans les documents, et avons essayé par moi-même, le tokenizer niveau de ElasticSearch sépare les mots sur les traits d'union, par exemple QNMZ-1900 sera divisé en QNMZ et 1900.

Pour éviter ce comportement, j'utilise la fonctionnalité not_analyzed.

curl -XPUT 'localhost:9200/test-idx' -d '{ 
"mappings": { 
    "doc": { 
     "properties": { 
      "foo" : { 
       "type": "string", 
       "index": "not_analyzed" 
      } 
     } 
    } 
} 
}' 

je mets quelque chose dans mon index:

curl -XPUT 'localhost:9200/test-idx/doc/1' -d '{"foo": "QNMZ-1900"}' 

Rafraîchissant il:

curl -XPOST 'localhost:9200/test-idx/_refresh' 

Maintenant, je peux utiliser une requête générique et trouver QNMZ-1900:

curl 'localhost:9200/test-idx/doc/_search?pretty=true' -d '{ 
"query": { 
    "wildcard" : { "foo" : "QNMZ-19*" } 
} 

Ma question:

Comment puis-je exécuter une requête générique avec un terme de recherche en minuscules?

J'ai essayé:

curl -XDELETE 'localhost:9200/test-idx' 
curl -XPUT 'localhost:9200/test-idx' -d '{ 
"mappings": { 
    "doc": { 
     "properties": { 
      "foo" : { 
       "type": "string", 
       "index": "not_analyzed", 
       "filter": "lowercase" 
      } 
     } 
    } 
} 
}' 
curl -XPUT 'localhost:9200/test-idx/doc/1' -d '{"foo": "QNMZ-1900"}' 
curl -XPOST 'localhost:9200/test-idx/_refresh' 

mais ma requête en minuscule:

curl 'localhost:9200/test-idx/doc/_search?pretty=true' -d '{ 
"query": { 
    "wildcard" : { "foo" : "qnmz-19*" } 
} 
}' 

ne trouve rien.

Comment le réparer?

Répondre

4

Une solution consiste à définir un analyseur personnalisé à l'aide

  • un keyword tokenizer (qui maintient la valeur d'entrée telle qu'elle est, comme si elle était not_analyzed)
  • un lowercase tokenfilter

J'ai essayé ceci:

POST test-idx 
{ 
    "index":{ 
    "analysis":{ 
     "analyzer":{ 
     "lowercase_hyphen":{ 
      "type":"custom", 
      "tokenizer":"keyword", 
      "filter":["lowercase"] 
     } 
     } 
    } 
    } 
} 

PUT test-idx/doc/_mapping 
{ 
    "doc":{ 
    "properties": { 
     "foo" : { 
      "type": "string", 
      "analyzer": "lowercase_hyphen" 
     } 
    }  
    } 
} 

POST test-idx/doc 
{ 
    "foo":"QNMZ-1900" 
} 

Comme vous pouvez le voir en utilisant le point de terminaison _analyze comme ceci:

GET test-idx/_analyze?analyzer=lowercase_hyphen&text=QNMZ-1900 

sorties seulement un jeton en minuscules mais pas divisés sur les traits d'union:

{ 
    "tokens": [ 
     { 
     "token": "qnmz-1900", 
     "start_offset": 0, 
     "end_offset": 9, 
     "type": "word", 
     "position": 1 
     } 
    ] 
} 

Puis, en utilisant la même requête:

POST test-idx/doc/_search 
{ 
    "query": { 
    "wildcard" : { "foo" : "qnmz-19*" }  
    } 
} 

J'ai ce résultat, qui est ce que vous voulez:

{ 
    "took": 66, 
    "timed_out": false, 
    "_shards": { 
     "total": 5, 
     "successful": 5, 
     "failed": 0 
    }, 
    "hits": { 
     "total": 1, 
     "max_score": 1, 
     "hits": [ 
     { 
      "_index": "test-idx", 
      "_type": "doc", 
      "_id": "wo1yanIjQGmvgfScMg4hyg", 
      "_score": 1, 
      "_source": { 
       "foo": "QNMZ-1900" 
      } 
     } 
     ] 
    } 
} 

Cependant, veuillez noter que cela vous permettra d'interroger uniquement en utilisant valeur minuscule. Comme indiqué par Andrei dans le commentaire, la même requête avec la valeur QNMZ-19* ne retournera rien.

La raison peut être trouvée dans le documentation: au moment de la recherche, la valeur n'est pas analysée.

+0

ne semble pas fonctionner pour POST test IDX/doc/_search { "requête": { "joker": { "foo": "QNMZ-19 *"}} } –

+1

En effet, l'entrée de requête générique n'est pas analysée, mais de cette façon, la recherche peut toujours être effectuée sur la valeur en minuscule. Cependant, je mets à jour ma réponse. – ThomasC

+0

@ThomasC cette réponse est-elle toujours valable pour ElasticSearch 6.1? Existe-t-il une fonctionnalité plus récente et plus pratique pour ce type de recherche? Que penses-tu des différents types de modélisation? Dans l'exemple, nous pourrions dupliquer "foo" dans le champ "foo_lowercase" dans json qui contiendrait "qnmz-1900". Et puis nous pourrions rechercher par curl 'localhost: 9200/test-idx/doc/_search? Pretty = true' -d '{"requête": {"wildcard": {"foo": "qnmz-19 *"} } Ou considérez-vous ce type de modélisation comme un anti-modèle pour la recherche élastique? –

0

J'ai vérifié cette approche dans mon projet de compagnie basé sur ES 6.1. Modèle de données comme ci-dessous permet de rechercher comme prévu en question:

PUT test-idx 
{ 
    "settings": { 
     "analysis": { 
      "analyzer": { 
       "keylower": { 
        "type": "custom", 
        "tokenizer": "keyword", 
        "filter": ["lowercase"] 
       } 
      } 
     } 
    } 
} 

POST /test-idx/doc/_mapping 
{ 
    "properties": { 
     "foo": { 
      "type": "text", 
      "fields": { 
       "raw": { 
        "type": "keyword" 
       }, 
       "lowercase_foo": { 
        "type": "text", 
        "analyzer": "keylower" 
       } 
      } 
     } 
    } 
} 

PUT /test-idx/doc/1 
{"foo": "QNMZ-1900"} 

Vérifiez les résultats de ces deux recherches. Premièrement, resoult un coup. Le second retournera 0 hits.

GET /test-idx/doc/_search 
{ 
    "query": { 
    "wildcard" : { "foo.lowercase_foo" : "qnmz-19*" } 
    } 
} 

GET /test-idx/doc/_search 
{ 
    "query": { 
    "wildcard" : { "foo" : "qnmz-19*" } 
    } 
} 

Merci à @ThomasC pour un avis. S'il vous plaît soyez prudent avec ma réponse. Je suis en train d'apprendre Elasticsearch. Je ne suis pas un expert dans cette base de données. Je ne sais pas, c'est un conseil prêt pour la production!

Questions connexes