Estoy usando elasticsearch para indexar mis documentos.
¿Es posible indicarle que solo devuelva campos particulares en lugar del documento json completo que ha almacenado?
Estoy usando elasticsearch para indexar mis documentos.
¿Es posible indicarle que solo devuelva campos particulares en lugar del documento json completo que ha almacenado?
Respuestas:
¡Sí! Usa un filtro fuente . Si está buscando con JSON, se verá así:
{
"_source": ["user", "message", ...],
"query": ...,
"size": ...
}
En ES 2.4 y versiones anteriores, también podría usar la opción de campos para la API de búsqueda :
{
"fields": ["user", "message", ...],
"query": ...,
"size": ...
}
Esto está en desuso en ES 5+. ¡Y los filtros fuente son más potentes de todos modos!
Encontré los documentos para get api
que sean útiles, especialmente las dos secciones, Filtrado de origen y Campos : https://www.elastic.co/guide/en/elasticsearch/reference/7.3/docs-get.html#get-source- filtración
Afirman sobre el filtrado de origen:
Si solo necesita uno o dos campos del _source completo, puede usar los parámetros _source_include y _source_exclude para incluir o filtrar las partes que necesita. Esto puede ser especialmente útil con documentos grandes donde la recuperación parcial puede ahorrar en la sobrecarga de la red
Lo cual se ajustaba perfectamente a mi caso de uso. Terminé simplemente filtrando la fuente así (usando la abreviatura):
{
"_source": ["field_x", ..., "field_y"],
"query": {
...
}
}
Para su información, indican en los documentos sobre el parámetro de campos :
La operación get permite especificar un conjunto de campos almacenados que se devolverán al pasar el parámetro de los campos.
Parece atender los campos que se han almacenado específicamente, donde coloca cada campo en una matriz. Si los campos especificados no se han almacenado, obtendrá cada uno de _source, lo que podría resultar en recuperaciones 'más lentas'. También tuve problemas para intentar que devolviera campos de tipo objeto.
En resumen, tiene dos opciones, ya sea mediante el filtrado de origen o los campos [almacenados].
For the ES versions 5.X and above you can a ES query something like this
GET /.../...
{
"_source": {
"includes": [ "FIELD1", "FIELD2", "FIELD3" ... " ]
},
.
.
.
.
}
En Elasticsearch 5.x, el enfoque mencionado anteriormente está en desuso. Puede usar el enfoque _source, pero en ciertas situaciones puede tener sentido almacenar un campo. Por ejemplo, si tiene un documento con un título, una fecha y un campo de contenido muy grande, es posible que desee recuperar solo el título y la fecha sin tener que extraer esos campos de un campo _source grande:
En este caso, usarías:
{
"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":{
}
}
Consulte la documentación sobre cómo indexar los campos almacenados. ¡Siempre feliz por un voto a favor!
Todas las API REST aceptan un parámetro filter_path que se puede usar para reducir la respuesta devuelta por elasticsearch. Este parámetro toma una lista de filtros separados por comas expresados con la notación de puntos.
Aquí otra solución, ahora usando una expresión de coincidencia
Filtrado de fuente
Permite controlar cómo se devuelve el campo _source con cada golpe.
Probado con Elastiscsearch versión 5.5
La palabra clave "incluye" define los campos específicos.
GET /my_indice/my_indice_type/_search
{
"_source": {
"includes": [ "my_especific_field"]
},
"query": {
"bool": {
"must": [
{"match": {
"_id": "%my_id_here_without_percent%"
}
}
]
}
}
}
Se podría realizar una solicitud REST API GET con el parámetro '_source'.
Solicitud de ejemplo
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
Respuesta
{
"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
}
}
]
}
}
Sí, mediante el uso del filtro fuente puede lograr esto, aquí está el filtro fuente de documentos
Solicitud de ejemplo
POST index_name/_search
{
"_source":["field1","filed2".....]
}
La salida será
{
"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 puedes usar setFetchSource de esta manera:
client.prepareSearch(index).setTypes(type)
.setFetchSource(new String[] { "field1", "field2" }, null)
Por ejemplo, tiene un documento con tres campos:
PUT movie/_doc/1
{
"name":"The Lion King",
"language":"English",
"score":"9.3"
}
Si desea regresar name
y score
puede usar el siguiente comando:
GET movie/_doc/1?_source_includes=name,score
Si desea obtener algunos campos que coinciden con un patrón:
GET movie/_doc/1?_source_includes=*re
Quizás excluir algunos campos:
GET movie/_doc/1?_source_excludes=score
Con la API de Java, uso lo siguiente para obtener todos los registros de un conjunto de campos particulares:
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;
}