J'utilise elasticsearch pour indexer mes documents.
Est-il possible de lui demander de ne renvoyer que des champs particuliers au lieu du document JSON entier qu'il a stocké?
Oui! Utilisez un filtre source . Si vous recherchez avec JSON, cela ressemblera à ceci:
{
"_source": ["user", "message", ...],
"query": ...,
"size": ...
}
Dans ES 2.4 et les 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 de source sont quand même plus puissants!
J'ai trouvé la documentation pour le get api
utile, notamment les deux sections Filtrage de la source et Champs : - https://www.elastic.co/guide/fr/elasticsearch/reference/7.3/docs-get.html#get-source-filtering
Ils déclarent à propos du filtrage de source:
Si vous n'avez besoin que d'un ou deux champs de la source complète _source, 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 pour les documents volumineux où la récupération partielle peut réduire les frais généraux du réseau.
Ce qui convenait parfaitement à mon cas d'utilisation. J'ai fini par filtrer simplement la source comme suit (en utilisant le raccourci):
{
"_source": ["field_x", ..., "field_y"],
"query": {
...
}
}
Pour votre information, ils indiquent dans la documentation à propos du paramètre field :
L'opération get permet de spécifier un ensemble de champs stockés qui seront renvoyé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, chacun d'eux sera extrait de la source _source, ce qui pourrait entraîner des extractions 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 le filtrage de la source, soit les 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 susmentionnée est obsolète. 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 très grand champ de contenu, vous pouvez extraire uniquement le titre et la date sans avoir à extraire ces champs d'un gros 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":{
}
}
Voir la documentation sur la façon d'indexer les champs stockés. Toujours heureux pour un vote positif!
Toutes les API REST acceptent un paramètre filter_path pouvant ê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 correspondante
filtrage de la source
Permet de contrôler la manière dont le champ _source est renvoyé à chaque hit.
Testé avec Elastiscsearch version 5.5
Le mot clé "includes" 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%"
}
}
]
}
}
}
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" }
}
}
Une requête 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
}
}
]
}
}
Dans Java, vous pouvez utiliser setFetchSource comme ceci:
client.prepareSearch(index).setTypes(type)
.setFetchSource(new String[] { "field1", "field2" }, null)
Oui, en utilisant le filtre source, vous pouvez le faire, voici la doc filtrage par la source
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"
},....
}
]
}
}
Par exemple, vous avez un doc avec trois champs:
PUT moive/_doc/1
{
"name":"The Lion King",
"language":"English",
"score":"9.3"
}
si vous voulez retourner name
et score
, vous pouvez utiliser la commande suivante:
GET moive/_doc/1?_source_includes=name,score
Si vous voulez obtenir un champ avec un motif:
GET moive/_doc/1?_source_includes=*re
Peut-être sauf quelques champs:
GET moive/_doc/1?_source_excludes=score