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é?
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é?
Réponses:
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!
J'ai trouvé les documents get api
utiles 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].
For the ES versions 5.X and above you can a ES query something like this
GET /.../...
{
"_source": {
"includes": [ "FIELD1", "FIELD2", "FIELD3" ... " ]
},
.
.
.
.
}
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!
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.
Voici une autre solution, utilisant maintenant une expression de correspondance
Filtrage source
Permet de contrôler la façon dont le champ _source est renvoyé à chaque hit.
Testé avec Elastiscsearch version 5.5
Le mot-clé "comprend" définit les champs spécifiques.
GET /my_indice/my_indice_type/_search
{
"_source": {
"includes": [ "my_especific_field"]
},
"query": {
"bool": {
"must": [
{"match": {
"_id": "%my_id_here_without_percent%"
}
}
]
}
}
}
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
}
}
]
}
}
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"
},....
}
]
}
}
En java, vous pouvez utiliser setFetchSource comme ceci:
client.prepareSearch(index).setTypes(type)
.setFetchSource(new String[] { "field1", "field2" }, null)
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 name
et score
vous 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
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;
}