Faire elasticsearch ne renvoie que certains champs?

434

J'utilise elasticsearch pour indexer mes documents.

Est-il possible de lui demander de renvoyer uniquement des champs particuliers au lieu du document json entier qu'il a stocké?

user1199438
la source
1
elastic.co/guide/en/elasticsearch/reference/current/… , notez que vous ne pouvez également exclure que certains champs
Christophe Roussy

Réponses:

620

Oui! Utilisez un filtre source . Si vous recherchez avec JSON, cela ressemblera à ceci:

{
    "_source": ["user", "message", ...],
    "query": ...,
    "size": ...
}

Dans ES 2.4 et versions antérieures, vous pouvez également utiliser l' option champs de l'API de recherche :

{
    "fields": ["user", "message", ...],
    "query": ...,
    "size": ...
}

Ceci est déconseillé dans ES 5+. Et les filtres sources sont de toute façon plus puissants!

kevingessner
la source
12
assurez-vous de les définir comme "stockés": vrai dans le mappage. Sinon, ES chargera toujours le document _source et chargera les champs à partir de là. Peut affecter les performances si les données renvoyées sont relativement petites par rapport à la taille d'un document entier.
Zaar Hai
6
vous vouliez dire "magasin": vrai
sscarduzio
sont-ils faits dans le fichier conf ou où exactement?
vbNewbie
@vbNewbie: Où que vous définissiez la cartographie. Si vous ne définissez pas le mappage de manière explicite et ne comptez pas sur ES pour le générer, vous devrez définir le mappage pour les champs que vous souhaitez que ES stocke. Vous pouvez définir le mappage uniquement pour les champs pour lesquels vous souhaitez un comportement spécial (par exemple, "store": true, "index": "not_analyzed") ou tous les champs. Consultez les documents de mappage pour plus de détails.
Sangharsh
3
champs n'est plus pris en charge sur les versions plus récentes. utilisez plutôt stored_fields :)
Sachin Sharma
88

J'ai trouvé les documents get apiutiles pour - en particulier les deux sections, Filtrage des sources et Champs : https://www.elastic.co/guide/en/elasticsearch/reference/7.3/docs-get.html#get-source- filtration

Ils déclarent sur le filtrage des sources:

Si vous n'avez besoin que d'un ou deux champs de la _source complète, vous pouvez utiliser les paramètres _source_include & _source_exclude pour inclure ou filtrer les pièces dont vous avez besoin. Cela peut être particulièrement utile avec des documents volumineux où la récupération partielle peut économiser sur la surcharge du réseau

Ce qui correspondait parfaitement à mon cas d'utilisation. J'ai fini par simplement filtrer la source comme ça (en utilisant la sténographie):

{
    "_source": ["field_x", ..., "field_y"],
    "query": {      
        ...
    }
}

Pour info, ils déclarent dans la documentation sur le paramètre champs :

L'opération get permet de spécifier un ensemble de champs stockés qui seront retournés en passant le paramètre fields.

Il semble répondre aux champs qui ont été spécifiquement stockés, où il place chaque champ dans un tableau. Si les champs spécifiés n'ont pas été stockés, ils seront récupérés chacun à partir de la source _, ce qui pourrait entraîner des récupérations «plus lentes». J'ai également eu du mal à le faire renvoyer des champs de type objet.

Donc, en résumé, vous avez deux options, soit par filtrage de source, soit par champs [stockés].

Markus Coetzee
la source
A fait l'affaire pour moi. J'ai eu un problème avec le retour de geo_point en utilisant "champs", mais "_source" fonctionne très bien, merci!
Yonnaled
23
For the ES versions 5.X and above you can a ES query something like this

    GET /.../...
    {
      "_source": {
        "includes": [ "FIELD1", "FIELD2", "FIELD3" ... " ]
      },
      .
      .
      .
      .
    }
Pinkesh Sharma
la source
12

Dans Elasticsearch 5.x, l'approche mentionnée ci-dessus est déconseillée. Vous pouvez utiliser l'approche _source, mais dans certaines situations, il peut être judicieux de stocker un champ. Par exemple, si vous avez un document avec un titre, une date et un champ de contenu très volumineux, vous souhaiterez peut-être récupérer uniquement le titre et la date sans avoir à extraire ces champs d'un grand champ _source:

Dans ce cas, vous utiliseriez:

{  
   "size": $INT_NUM_OF_DOCS_TO_RETURN,
   "stored_fields":[  
      "doc.headline",
      "doc.text",
      "doc.timestamp_utc"
   ],
   "query":{  
      "bool":{  
         "must":{  
            "term":{  
               "doc.topic":"news_on_things"
            }
         },
         "filter":{  
            "range":{  
               "doc.timestamp_utc":{  
                  "gte":1451606400000,
                  "lt":1483228800000,
                  "format":"epoch_millis"
               }
            }
         }
      }
   },
   "aggs":{  

   }
}

Consultez la documentation sur l'indexation des champs stockés. Toujours heureux pour un Upvote!

woltob
la source
7
here you can specify whichever field you want in your output and also which you don't.

  POST index_name/_search
    {
        "_source": {
            "includes": [ "field_name", "field_name" ],
            "excludes": [ "field_name" ]
        },
        "query" : {
            "match" : { "field_name" : "value" }
        }
    }
Gaurav
la source
7

response_filtering

Toutes les API REST acceptent un paramètre filter_path qui peut être utilisé pour réduire la réponse renvoyée par elasticsearch. Ce paramètre prend une liste de filtres séparés par des virgules exprimés avec la notation par points.

https://stackoverflow.com/a/35647027/844700

Le Demz
la source
5

Une demande REST API GET peut être effectuée avec le paramètre '_source'.

Exemple de demande

http://localhost:9200/opt_pr/_search?q=SYMBOL:ITC AND OPTION_TYPE=CE AND TRADE_DATE=2017-02-10 AND EXPIRY_DATE=2017-02-23&_source=STRIKE_PRICE

Réponse

{
"took": 59,
"timed_out": false,
"_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
},
"hits": {
    "total": 104,
    "max_score": 7.3908954,
    "hits": [
        {
            "_index": "opt_pr",
            "_type": "opt_pr_r",
            "_id": "AV3K4QTgNHl15Mv30uLc",
            "_score": 7.3908954,
            "_source": {
                "STRIKE_PRICE": 160
            }
        },
        {
            "_index": "opt_pr",
            "_type": "opt_pr_r",
            "_id": "AV3K4QTgNHl15Mv30uLh",
            "_score": 7.3908954,
            "_source": {
                "STRIKE_PRICE": 185
            }
        },
        {
            "_index": "opt_pr",
            "_type": "opt_pr_r",
            "_id": "AV3K4QTgNHl15Mv30uLi",
            "_score": 7.3908954,
            "_source": {
                "STRIKE_PRICE": 190
            }
        },
        {
            "_index": "opt_pr",
            "_type": "opt_pr_r",
            "_id": "AV3K4QTgNHl15Mv30uLm",
            "_score": 7.3908954,
            "_source": {
                "STRIKE_PRICE": 210
            }
        },
        {
            "_index": "opt_pr",
            "_type": "opt_pr_r",
            "_id": "AV3K4QTgNHl15Mv30uLp",
            "_score": 7.3908954,
            "_source": {
                "STRIKE_PRICE": 225
            }
        },
        {
            "_index": "opt_pr",
            "_type": "opt_pr_r",
            "_id": "AV3K4QTgNHl15Mv30uLr",
            "_score": 7.3908954,
            "_source": {
                "STRIKE_PRICE": 235
            }
        },
        {
            "_index": "opt_pr",
            "_type": "opt_pr_r",
            "_id": "AV3K4QTgNHl15Mv30uLw",
            "_score": 7.3908954,
            "_source": {
                "STRIKE_PRICE": 260
            }
        },
        {
            "_index": "opt_pr",
            "_type": "opt_pr_r",
            "_id": "AV3K4QTgNHl15Mv30uL5",
            "_score": 7.3908954,
            "_source": {
                "STRIKE_PRICE": 305
            }
        },
        {
            "_index": "opt_pr",
            "_type": "opt_pr_r",
            "_id": "AV3K4QTgNHl15Mv30uLd",
            "_score": 7.381078,
            "_source": {
                "STRIKE_PRICE": 165
            }
        },
        {
            "_index": "opt_pr",
            "_type": "opt_pr_r",
            "_id": "AV3K4QTgNHl15Mv30uLy",
            "_score": 7.381078,
            "_source": {
                "STRIKE_PRICE": 270
            }
        }
    ]
}

}

Ironluca
la source
C'est très complet pour moi.
Thusitha Indunil
4

Oui, en utilisant le filtre source, vous pouvez accomplir cela, voici le doc source-filtering

Exemple de demande

POST index_name/_search
 {
   "_source":["field1","filed2".....] 
 }

La sortie sera

{
  "took": 57,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "index_name",
        "_type": "index1",
        "_id": "1",
        "_score": 1,
        "_source": {
          "field1": "a",
          "field2": "b"
        },
        {
          "field1": "c",
          "field2": "d"
        },....
      }
    ]
  }
}
RCP
la source
2

En java, vous pouvez utiliser setFetchSource comme ceci:

client.prepareSearch(index).setTypes(type)
            .setFetchSource(new String[] { "field1", "field2" }, null)
user1693371
la source
2

Par exemple, vous avez un document avec trois champs:

PUT movie/_doc/1
{
  "name":"The Lion King",
  "language":"English",
  "score":"9.3"
}

Si vous souhaitez revenir nameet scorevous pouvez utiliser la commande suivante:

GET movie/_doc/1?_source_includes=name,score

Si vous souhaitez obtenir des champs qui correspondent à un modèle:

GET movie/_doc/1?_source_includes=*re

Peut-être exclure certains champs:

GET movie/_doc/1?_source_excludes=score
Yao Pan
la source
0

En utilisant l'API Java, j'utilise ce qui suit pour obtenir tous les enregistrements d'un ensemble de champs particuliers:

public List<Map<String, Object>> getAllDocs(String indexName) throws IOException{
    int scrollSize = 1000;
    List<Map<String,Object>> data = new ArrayList<>();
    SearchResponse response = null;
    while( response == null || response.getHits().getHits().length != 0){
        response = client.prepareSearch(indexName)
            .setTypes("typeName")  // The document types to execute the search against. Defaults to be executed against all types.
        .setQuery(QueryBuilders.matchAllQuery())
        .setFetchSource(new String[]{"field1", "field2"}, null)
        .setSize(scrollSize)
        .execute()
        .actionGet();
        for(SearchHit hit : response.getHits()){
            System.out.println(hit.getSourceAsString());
        }
    }
    return data;
}
Est ce que je
la source