J'ai essayé de filtrer avec elasticsearch uniquement les documents contenant une chaîne vide dans son corps. Jusqu'à présent, je n'ai pas de chance.
Avant de continuer, je dois mentionner que j'ai déjà essayé les nombreuses "solutions" disséminées sur Interwebz et StackOverflow.
Voici donc la requête que j'essaie d'exécuter, suivie de ses homologues:
{
"query": {
"filtered":{
"filter": {
"bool": {
"must_not": [
{
"missing":{
"field":"_textContent"
}
}
]
}
}
}
}
}
J'ai aussi essayé ce qui suit:
{
"query": {
"filtered":{
"filter": {
"bool": {
"must_not": [
{
"missing":{
"field":"_textContent",
"existence":true,
"null_value":true
}
}
]
}
}
}
}
}
Et les suivants:
{
"query": {
"filtered":{
"filter": {
"missing": {"field": "_textContent"}
}
}
}
}
Aucun de ce qui précède n'a fonctionné. Je reçois un résultat vide quand je sais avec certitude qu'il existe des enregistrements contenant un champ de chaîne vide.
Si quelqu'un peut me fournir de l'aide, je vous en serai très reconnaissant.
Merci!
Si vous utilisez l'analyseur par défaut (standard
), rien ne lui permet d'analyser s'il s'agit d'une chaîne vide. Vous devez donc indexer le champ textuellement (non analysé). Voici un exemple:
Ajoutez un mappage qui indexera le champ sans tabou. Si vous avez également besoin d’une copie sous forme de jetons du champ indexé, vous pouvez utiliser un Multi Field type.
PUT http://localhost:9200/test/_mapping/demo
{
"demo": {
"properties": {
"_content": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
Ensuite, indexez quelques documents.
/POST http://localhost:9200/test/demo/1/
{
"_content": ""
}
/POST http://localhost:9200/test/demo/2
{
"_content": "some content"
}
Effectuer une recherche:
POST http://localhost:9200/test/demo/_search
{
"query": {
"filtered": {
"filter": {
"term": {
"_content": ""
}
}
}
}
}
Renvoie le document avec la chaîne vide.
{
took: 2,
timed_out: false,
_shards: {
total: 5,
successful: 5,
failed: 0
},
hits: {
total: 1,
max_score: 0.30685282,
hits: [
{
_index: test,
_type: demo,
_id: 1,
_score: 0.30685282,
_source: {
_content: ""
}
}
]
}
}
Même avec l’analyseur par défaut, vous pouvez effectuer ce type de recherche: utilisez un filtre script , qui est plus lent mais qui peut gérer la chaîne vide:
curl -XPOST 'http://localhost:9200/test/demo/_search' -d '
{
"query": {
"filtered": {
"filter": {
"script": {
"script": "_source._content.length() == 0"
}
}
}
}
}'
Il retournera le document avec une chaîne vide sous la forme _content sans un mappage spécial.
Comme indiqué par @js_gandalf, ceci est obsolète pour ES> 5.0. A la place, vous devez utiliser: query-> bool-> filter-> script comme dans https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
Pour ceux d'entre vous qui utilisent une recherche élastique 5.2 ou supérieure et qui restent bloqués. Le moyen le plus simple est de réindexer correctement vos données avec le type de mot clé. Ensuite, toutes les recherches de valeurs vides ont fonctionné. Comme ça:
"query": {
"term": {"MY_FIELD_TO_SEARCH": ""}
}
En fait, lorsque je réindexe ma base de données et réexécute la requête. Cela a fonctionné =)
Le problème était que mon champ était de type: texte et PAS un mot clé. Changement de l'index en mot clé et réindexation:
curl -X PUT https://username:[email protected]:9200/mycoolindex
curl -X PUT https://user:[email protected]:9200/mycoolindex/_mapping/mycooltype -d '{
"properties": {
"MY_FIELD_TO_SEARCH": {
"type": "keyword"
},
}'
curl -X PUT https://username:[email protected]:9200/_reindex -d '{
"source": {
"index": "oldindex"
},
"dest": {
"index": "mycoolindex"
}
}'
J'espère que cela aidera quelqu'un qui était aussi bloqué que je trouvais ces valeurs vides.
afin de trouver la chaîne vide d'un champ dans votre document, il est très important pour le mappage du champ, dans Word, son paramètre index
/analyzer
.
Si son index est not_analyzed
, ce qui signifie que le jeton est simplement une chaîne vide, vous pouvez simplement utiliser la requête term
pour le trouver, comme suit:
{"from": 0, "size": 100, "query":{"term": {"name":""}}}
Sinon, si le paramètre index
est analyzed
et que la plupart des analyseurs considèrent la chaîne vide comme une valeur nulle Sovous pouvez utiliser le filtre pour rechercher la chaîne vide.
{"filter": {"missing": {"existence": true, "field": "name", "null_value": true}}, "query": {"match_all": {}}}
voici le script Gist que vous pouvez référencer: https://Gist.github.com/hxuanji/35b982b86b3601cb5571
BTW, je vérifie les commandes que vous avez fournies, il semble que vous ne voulez PAS le document de chaîne vide . Et toutes mes commandes ci-dessus ne sont que pour les trouver, il suffit donc de le mettre dans la partie must_not
de la requête bool
irait bien .My ES est 1.0.1.
Pour ES 1.3.0, le Gist que j'ai fourni ne peut pas trouver la chaîne vide. Il semble que cela ait été rapporté: https://github.com/elasticsearch/elasticsearch/issues/7348 . Attendons de voir comment ça se passe.
Quoi qu'il en soit, il fournit également une autre commande pour trouver
{"requête": { "filtré": { "filtre": { "ne pas": { "filtre": { "intervalle": { "prénom": { } } } } } }}}
name
est le nom du champ pour trouver la chaîne vide. Je l'ai testé sur ES 1.3.2.
J'utilise Elasticsearch 5.3 et j'avais des problèmes avec certaines des réponses ci-dessus.
Le corps suivant a fonctionné pour moi.
{
"query": {
"bool" : {
"must" : {
"script" : {
"script" : {
"inline": "doc['city'].empty",
"lang": "painless"
}
}
}
}
}
}
Remarque: vous devrez peut-être activer le fielddata pour les champs de texte, il est désactivé par défaut. Bien que je lise ceci: https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html avant de le faire.
Pour activer le fielddata pour un champ, par exemple. 'ville' sur l'index 'entreprise' avec le nom de type 'enregistrement' dont vous avez besoin:
PUT business/_mapping/record
{
"properties": {
"city": {
"type": "text",
"fielddata": true
}
}
}
Si vous ne voulez pas ou ne pouvez pas réindexer, il existe un autre moyen. :-)
Vous pouvez utiliser l'opérateur de négation et un caractère générique pour faire correspondre toute chaîne non vide *
GET /my_index/_search?q=!(fieldToLookFor:*)
Pour les champs imbriqués, utilisez:
curl -XGET "http://localhost:9200/city/_search?pretty=true" -d '{
"query" : {
"nested" : {
"path" : "country",
"score_mode" : "avg",
"query" : {
"bool": {
"must_not": {
"exists": {
"field": "country.name"
}
}
}
}
}
}
}'
NOTE: chemin et champ constituent ensemble pour la recherche. Changer au besoin pour que vous travailliez.
Pour les champs réguliers:
curl -XGET 'http://localhost:9200/city/_search?pretty=true' -d'{
"query": {
"bool": {
"must_not": {
"exists": {
"field": "name"
}
}
}
}
}'
OU en utilisant la syntaxe de chaîne de requête lucene
q =! (yourfield.keyword: "")
Voir Elastic Search Reference https://www.elastic.co/guide/fr/elasticsearch/reference/6.5/query-dsl-query-string-query.html#query-string-syntax
Solution trouvée ici https://github.com/elastic/elasticsearch/issues/7515 Cela fonctionne sans réindex.
PUT t/t/1
{
"textContent": ""
}
PUT t/t/2
{
"textContent": "foo"
}
GET t/t/_search
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "textContent"
}
}
],
"must_not": [
{
"wildcard": {
"textContent": "*"
}
}
]
}
}
}
Vous devez déclencher l'indexeur de mots clés en ajoutant .content à votre nom de champ. En fonction de la configuration de l'index d'origine, la procédure suivante "ne fonctionne" que pour moi à l'aide de AWS ElasticSearch v6.x.
GET /my_idx/_search?q=my_field.content: ""
Je n'ai pas réussi à rechercher des chaînes vides dans un champ de texte. Cependant, il semble fonctionner avec un champ de type mot clé. Je suggère donc ce qui suit:
delete /test_idx
put test_idx
{
"mappings" : {
"testMapping": {
"properties" : {
"tag" : {"type":"text"},
"content" : {"type":"text",
"fields" : {
"x" : {"type" : "keyword"}
}
}
}
}
}
}
put /test_idx/testMapping/1
{
"tag": "null"
}
put /test_idx/testMapping/2
{
"tag": "empty",
"content": ""
}
GET /test_idx/testMapping/_search
{
"query" : {
"match" : {"content.x" : ""}}}
}
}