Зробити еластичний пошук лише повернути певні поля?


434

Я використовую еластичний пошук, щоб індексувати свої документи.

Чи можна доручити йому повертати лише окремі поля замість всього документа json, який він зберігав?


1
ela.co/guide/en/elasticsearch/reference/current/… , зауважте, що ви можете також виключити лише деякі поля
Крістоф Руссі

Відповіді:


620

Так! Використовуйте джерельний фільтр . Якщо ви шукаєте в JSON, це буде виглядати приблизно так:

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

У ES 2.4 та новіших версіях ви також можете використовувати параметр полів для пошукового API :

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

Це застаріло в ES 5+. А джерельні фільтри все одно є більш потужними!


12
не забудьте визначити їх як "збережені": вірно в картографуванні. Інакше ES все ще завантажить звідти документ _source та завантажить поля. Може вплинути на ефективність, якщо повернені дані відносно невеликі до розміру всього документа.
Zaar Hai

6
ви мали на увазі "магазин": true
sscarduzio

вони зроблені у файлі conf або де саме?
vbNewbie

@vbNewbie: Де б ви ніколи не визначали карти. Якщо ви не визначаєте чітке відображення і покладаєтесь на ES для його створення, вам доведеться визначити відображення для полів, які потрібно зберігати. Ви можете визначити відображення лише для полів, де потрібно особливу поведінку (наприклад, "store": true, "index": "not_analyzed") або всіх полів. Подивіться на картографічні документи для отримання більш детальної інформації.
Сангхарш

3
поля більше не підтримуються в нових версіях. використовуйте натомість зберігаються_fields :)
Sachin Sharma

88

Я виявив, що документи get apiє корисними - особливо два розділи, фільтрування джерел і поля : https://www.elastic.co/guide/en/elasticsearch/reference/7.3/docs-get.html#get-source- фільтрація

Вони заявляють про фільтрацію джерел:

Якщо вам потрібно лише одне або два поля з повного _source, ви можете використовувати параметри _source_include & _source_exclude, щоб включити або відфільтрувати потрібні вам частини. Це може бути особливо корисно для великих документів, де часткове завантаження може економити накладні витрати в мережі

Що ідеально підходило моєму використанню. Я в кінцевому підсумку просто фільтрував джерело так (за допомогою скорочення):

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

FYI, вони в документах констатують параметр полів :

Операція get дозволяє вказати набір збережених полів, які будуть повернуті, передавши параметр поля.

Здається, задовольняє спеціально збережені поля, де вони розміщують кожне поле у ​​масиві. Якщо вказані поля не будуть збережені, вони отримують кожне з _source, що може призвести до "повільніших" пошуків. У мене також виникли проблеми, намагаючись змусити його повернути поля типу об'єкта.

Отже, підсумовуючи, у вас є два варіанти: фільтрування джерел або [збережені] поля.


Зробив трюк для мене. У мене виникла проблема із поверненням geo_point за допомогою "полів", але "_source" працює чудово, дякую!
Оновлено

23
For the ES versions 5.X and above you can a ES query something like this

    GET /.../...
    {
      "_source": {
        "includes": [ "FIELD1", "FIELD2", "FIELD3" ... " ]
      },
      .
      .
      .
      .
    }

12

У програмі Elasticsearch 5.x вищезазначений підхід застарів. Можна використовувати підхід _source, але в певних ситуаціях зберігати поле може мати сенс. Наприклад, якщо у вас є документ із заголовком, датою та дуже великим полем вмісту, ви можете отримати лише заголовок та дату, не виймаючи ці поля з великого поля ресурсу:

У цьому випадку ви використовуєте:

{  
   "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":{  

   }
}

Дивіться документацію про те, як індексувати збережені поля. Завжди раді за оновлення!


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" }
        }
    }

7

response_filtering

Усі API REST приймають параметр filter_path, який може бути використаний для зменшення відповіді, поверненої elastralsearch. Цей параметр містить список відокремлених комами фільтрів, виражених нотацією крапок.

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


6

Ось ще одне рішення, тепер використовується вираз відповідності

Фільтрація джерела
Дозволяє контролювати те, як повертається поле _source при кожному зверненні.

Протестовано у версії 5.5 Elastiscsearch

Ключове слово "включає" визначає поля специфіки.

GET /my_indice/my_indice_type/_search
{
    "_source": {
        "includes": [ "my_especific_field"]
        },
        "query": {
        "bool": {
                "must": [
                {"match": {
                    "_id": "%my_id_here_without_percent%"
                    }
                }
            ]
        }
    }
}

5

Запит RET API GET може бути зроблений з параметром '_source'.

Приклад запиту

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

Відповідь

{
"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
            }
        }
    ]
}

}


Це дуже корисне для мене використання.
Сукітта Індуніл

4

Так, використовуючи джерельний фільтр, ви можете досягти цього, ось фільтрування джерела документа

Приклад запиту

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

Вихід буде

{
  "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"
        },....
      }
    ]
  }
}

2

У Java ви можете використовувати setFetchSource так:

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

2

Наприклад, у вас є документ з трьома полями:

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

Якщо ви хочете , щоб повернутися nameі scoreви можете використовувати наступну команду:

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

Якщо ви хочете отримати кілька полів, які відповідають шаблону:

GET movie/_doc/1?_source_includes=*re

Можливо, виключіть деякі поля:

GET movie/_doc/1?_source_excludes=score

0

Використовуючи Java API, я використовую наступне, щоб отримати всі записи з набору певних полів:

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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.