Buat elasticsearch hanya mengembalikan bidang tertentu?

434

Saya menggunakan elasticsearch untuk mengindeks dokumen saya.

Apakah mungkin untuk menginstruksikannya hanya mengembalikan bidang tertentu dan bukan seluruh dokumen json yang telah disimpannya?

pengguna1199438
sumber
1
elastic.co/guide/en/elasticsearch/reference/current/… , perhatikan bahwa Anda juga dapat mengecualikan hanya beberapa bidang
Christophe Roussy

Jawaban:

620

Ya! Gunakan filter sumber . Jika Anda mencari dengan JSON akan terlihat seperti ini:

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

Di ES 2.4 dan sebelumnya, Anda juga bisa menggunakan opsi bidang ke API pencarian :

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

Ini tidak digunakan lagi dalam ES 5+. Dan filter sumber lebih kuat!

kevingessner
sumber
12
pastikan untuk mendefinisikannya sebagai "tersimpan": benar dalam pemetaan. Kalau tidak, ES masih akan memuat dokumen sumber dan memuat bidang dari sana. Dapat berdampak kinerja jika data yang dikembalikan relatif kecil dengan ukuran seluruh dokumen.
Zaar Hai
6
Anda berarti "toko": true
sscarduzio
apakah ini dibuat di file conf atau di mana tepatnya?
vbNewbie
@vbNewbie: Di mana pun Anda mendefinisikan pemetaan. Jika Anda tidak mendefinisikan pemetaan secara eksplisit dan mengandalkan ES untuk menghasilkannya, maka Anda harus menentukan pemetaan untuk bidang yang ingin Anda simpan ES. Anda dapat menentukan pemetaan hanya untuk bidang yang Anda inginkan perilaku khusus (mis. "Store": true, "index": "not_analyzed") atau semua bidang. Lihatlah ke dokumen pemetaan untuk detail lebih lanjut.
Sangharsh
3
bidang tidak lagi didukung pada versi yang lebih baru. alih-alih gunakan stored_fields :)
Sachin Sharma
88

Saya menemukan dokumen untuk get apimembantu - terutama dua bagian, Penyaringan sumber dan Bidang : https://www.elastic.co/guide/en/elasticsearch/reference/7.3/docs-get.html#get-source- penyaringan

Mereka menyatakan tentang pemfilteran sumber:

Jika Anda hanya membutuhkan satu atau dua bidang dari _source lengkap, Anda dapat menggunakan parameter _source_include & _source_exclude untuk menyertakan atau memfilter bagian yang Anda butuhkan. Ini dapat sangat membantu dengan dokumen besar di mana pengambilan sebagian dapat menghemat overhead jaringan

Yang pas dengan case saya. Saya akhirnya hanya memfilter sumber seperti itu (menggunakan singkatan):

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

FYI, mereka menyatakan dalam dokumen tentang parameter bidang :

Operasi dapatkan memungkinkan menentukan set bidang yang disimpan yang akan dikembalikan dengan melewati parameter bidang.

Tampaknya untuk memenuhi bidang yang telah disimpan secara khusus, di mana ia menempatkan masing-masing bidang dalam array. Jika bidang yang ditentukan belum disimpan, maka bidang tersebut akan diambil masing-masing dari sumber, yang dapat menyebabkan pengambilan lebih lambat. Saya juga mengalami kesulitan mencoba untuk mengembalikannya ke bidang tipe objek.

Jadi, secara ringkas, Anda memiliki dua opsi, baik pemfilteran sumber atau bidang [tersimpan].

Markus Coetzee
sumber
Apakah trik untuk saya. Saya punya masalah dengan mengembalikan geo_point menggunakan "bidang", tetapi "_source" berfungsi dengan baik, terima kasih!
Yonnaled
23
For the ES versions 5.X and above you can a ES query something like this

    GET /.../...
    {
      "_source": {
        "includes": [ "FIELD1", "FIELD2", "FIELD3" ... " ]
      },
      .
      .
      .
      .
    }
Pinkesh Sharma
sumber
12

Dalam Elasticsearch 5.x pendekatan yang disebutkan di atas sudah usang. Anda bisa menggunakan pendekatan _source, tetapi tetapi dalam situasi tertentu masuk akal untuk menyimpan bidang. Misalnya, jika Anda memiliki dokumen dengan judul, tanggal, dan bidang konten yang sangat besar, Anda mungkin ingin mengambil hanya judul dan tanggal tanpa harus mengekstrak bidang tersebut dari bidang _source besar:

Dalam hal ini, Anda akan menggunakan:

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

   }
}

Lihat dokumentasi tentang cara mengindeks bidang yang disimpan. Selalu bahagia untuk Suara positif!

woltob
sumber
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" }
        }
    }
Gaurav
sumber
7

filter_filter

Semua API REST menerima parameter filter_path yang dapat digunakan untuk mengurangi respons yang dikembalikan oleh elasticsearch. Parameter ini mengambil daftar filter yang dipisahkan koma yang dinyatakan dengan notasi titik.

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

Demz
sumber
5

Permintaan REST API GET dapat dibuat dengan parameter '_source'.

Contoh Permintaan

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

Tanggapan

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

}

Ironluca
sumber
Ini sangat bermanfaat bagi saya.
Thusitha Indunil
4

Ya dengan menggunakan filter sumber Anda dapat melakukan ini, ini adalah pemfilteran sumber dokumen

Contoh Permintaan

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

Output akan menjadi

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

Di java, Anda bisa menggunakan setFetchSource seperti ini:

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

Misalnya, Anda memiliki dokumen dengan tiga bidang:

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

Jika Anda ingin kembali namedan scoreAnda dapat menggunakan perintah berikut:

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

Jika Anda ingin mendapatkan beberapa bidang yang cocok dengan pola:

GET movie/_doc/1?_source_includes=*re

Mungkin mengecualikan beberapa bidang:

GET movie/_doc/1?_source_excludes=score
Yao Pan
sumber
0

Menggunakan Java API, saya menggunakan yang berikut ini untuk mendapatkan semua catatan dari sekumpulan bidang tertentu:

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;
}
Doi
sumber