Używam elasticsearch do indeksowania moich dokumentów.
Czy można poinstruować, aby zwracał tylko określone pola zamiast całego zapisanego dokumentu json?
Używam elasticsearch do indeksowania moich dokumentów.
Czy można poinstruować, aby zwracał tylko określone pola zamiast całego zapisanego dokumentu json?
Odpowiedzi:
Tak! Użyj filtra źródłowego . Jeśli szukasz w JSON, będzie wyglądać mniej więcej tak:
{
"_source": ["user", "message", ...],
"query": ...,
"size": ...
}
W ES 2.4 i wcześniejszych można również użyć opcji pól w interfejsie API wyszukiwania :
{
"fields": ["user", "message", ...],
"query": ...,
"size": ...
}
Jest to przestarzałe w ES 5+. A filtry źródłowe i tak są potężniejsze!
Uważam, że dokumenty get api
są pomocne - szczególnie dwie sekcje, Filtrowanie źródeł i Pola : https://www.elastic.co/guide/en/elasticsearch/reference/7.3/docs-get.html#get-source- filtracja
Mówią o filtrowaniu źródeł:
Jeśli potrzebujesz tylko jednego lub dwóch pól z pełnego _source, możesz użyć parametrów _source_include & _source_exclude, aby uwzględnić lub odfiltrować potrzebne części. Może to być szczególnie pomocne w przypadku dużych dokumentów, w których częściowe pobieranie może zaoszczędzić na narzutach sieciowych
Które idealnie pasowały do mojego przypadku użycia. Skończyło się na tym, że tak po prostu przefiltrowałem źródło (używając skrótu):
{
"_source": ["field_x", ..., "field_y"],
"query": {
...
}
}
Do Twojej wiadomości w dokumentach podają parametr parametr pola :
Operacja get umożliwia określenie zestawu przechowywanych pól, które zostaną zwrócone poprzez przekazanie parametru pola.
Wydaje się, że obsługuje pola, które zostały specjalnie zapisane, gdzie umieszcza każde pole w tablicy. Jeśli określone pola nie zostaną zapisane, pobierze każde z _source, co może spowodować „wolniejsze” pobieranie. Miałem również problemy z uzyskaniem go, aby zwracał pola typu obiektu.
Podsumowując, masz dwie opcje: filtrowanie źródła lub pola [przechowywane].
For the ES versions 5.X and above you can a ES query something like this
GET /.../...
{
"_source": {
"includes": [ "FIELD1", "FIELD2", "FIELD3" ... " ]
},
.
.
.
.
}
W Elasticsearch 5.x powyższe podejście jest przestarzałe. Możesz użyć metody _source, ale w niektórych sytuacjach sensowne jest przechowywanie pola. Na przykład, jeśli masz dokument z tytułem, datą i bardzo dużym polem zawartości, możesz pobrać tylko tytuł i datę bez konieczności wyodrębniania tych pól z dużego pola _source:
W takim przypadku użyłbyś:
{
"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":{
}
}
Zobacz dokumentację dotyczącą sposobu indeksowania przechowywanych pól. Zawsze chętny na upvote!
Wszystkie interfejsy API REST akceptują parametr ścieżka_filtru, którego można użyć do zmniejszenia odpowiedzi zwracanej przez wyszukiwanie elastyczne. Ten parametr przyjmuje listę filtrów oddzielonych przecinkami wyrażonych notacją kropkową.
Oto inne rozwiązanie, teraz wykorzystujące wyrażenie dopasowania
Filtrowanie źródła
Pozwala kontrolować sposób zwracania pola _source przy każdym trafieniu.
Testowane z Elastiscsearch w wersji 5.5
Słowo kluczowe „zawiera” określa pola szczegółowe.
GET /my_indice/my_indice_type/_search
{
"_source": {
"includes": [ "my_especific_field"]
},
"query": {
"bool": {
"must": [
{"match": {
"_id": "%my_id_here_without_percent%"
}
}
]
}
}
}
Żądanie GET API REST można wykonać za pomocą parametru „_source”.
Przykładowe zapytanie
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
Odpowiedź
{
"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
}
}
]
}
}
Tak, korzystając z filtru źródłowego, możesz to zrobić, oto filtrowanie źródłowe dokumentów
Przykładowe zapytanie
POST index_name/_search
{
"_source":["field1","filed2".....]
}
Wyjście będzie
{
"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"
},....
}
]
}
}
W Javie możesz użyć setFetchSource w następujący sposób:
client.prepareSearch(index).setTypes(type)
.setFetchSource(new String[] { "field1", "field2" }, null)
Na przykład masz dokument z trzema polami:
PUT movie/_doc/1
{
"name":"The Lion King",
"language":"English",
"score":"9.3"
}
Jeśli chcesz wrócić name
i score
możesz użyć następującego polecenia:
GET movie/_doc/1?_source_includes=name,score
Jeśli chcesz uzyskać pola pasujące do wzorca:
GET movie/_doc/1?_source_includes=*re
Może wykluczyć niektóre pola:
GET movie/_doc/1?_source_excludes=score
Korzystając z Java API, używam następujących elementów, aby uzyskać wszystkie rekordy z zestawu określonych pól:
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;
}