ทำให้ elasticsearch คืนค่าบางฟิลด์เท่านั้นหรือไม่


434

ฉันใช้ elasticsearch เพื่อจัดทำดัชนีเอกสารของฉัน

เป็นไปได้ไหมที่จะสั่งให้ส่งคืนเฉพาะบางฟิลด์แทนที่จะเป็นเอกสาร json ทั้งหมดที่เก็บไว้?


1
elastic.co/guide/en/elasticsearch/reference/current/…โปรดทราบว่าคุณสามารถยกเว้นเฉพาะบางฟิลด์ได้ด้วย
Christophe Roussy

คำตอบ:


620

อ้อ! ใช้ตัวกรองที่มา หากคุณกำลังค้นหาด้วย JSON มันจะมีลักษณะดังนี้:

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

ใน ES 2.4 และรุ่นก่อนหน้าคุณสามารถใช้ตัวเลือกฟิลด์กับ API การค้นหา :

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

เลิกใช้แล้วใน ES 5+ และแหล่งตัวกรองมีประสิทธิภาพมากขึ้นต่อไป!


12
ตรวจสอบให้แน่ใจว่าได้กำหนดเป็น "เก็บไว้": เป็นจริงในการจับคู่ มิฉะนั้น ES จะยังคงโหลด _source เอกสารและโหลดเขตข้อมูลจากที่นั่น อาจส่งผลกระทบต่อประสิทธิภาพหากข้อมูลที่ส่งคืนมีขนาดค่อนข้างเล็กตามขนาดของเอกสารทั้งหมด
Zaar Hai

6
คุณหมายถึง "store": true
sscarduzio

ทำในไฟล์ conf หรือที่ไหนกันแน่?
vbNewbie

@vbNewbie: ไม่ว่าคุณจะกำหนดแผนที่ไว้ที่ไหน หากคุณไม่ได้กำหนดแผนที่อย่างชัดเจนและพึ่งพา ES เพื่อสร้างมันขึ้นมาคุณจะต้องกำหนดการแมปสำหรับฟิลด์ที่คุณต้องการให้ ES จัดเก็บ คุณสามารถกำหนดการแมปสำหรับฟิลด์ที่คุณต้องการพฤติกรรมพิเศษ (เช่น "store": true, "index": "not_analyzed") หรือฟิลด์ทั้งหมด ค้นหาเอกสารการทำแผนที่เพื่อดูรายละเอียดเพิ่มเติม
Sangharsh

3
เขตข้อมูลไม่ได้รับการสนับสนุนในรุ่นที่ใหม่กว่าอีกต่อไป ใช้ hidden_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" ใช้งานได้ดีขอบคุณ!
Yonnaled


12

ใน Elasticsearch 5.x วิธีการที่กล่าวถึงข้างต้นถูกคัดค้าน คุณสามารถใช้วิธี _source ได้ แต่ในบางสถานการณ์อาจใช้วิธีจัดเก็บฟิลด์ ตัวอย่างเช่นหากคุณมีเอกสารที่มีชื่อเรื่องวันที่และฟิลด์เนื้อหาที่มีขนาดใหญ่มากคุณอาจต้องการดึงเฉพาะชื่อและวันที่โดยไม่ต้องแยกฟิลด์เหล่านั้นออกจากฟิลด์ _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

REST APIs ทั้งหมดยอมรับพารามิเตอร์ filter_path ที่สามารถใช้เพื่อลดการตอบกลับที่ส่งกลับโดย elasticsearch พารามิเตอร์นี้ใช้รายการของตัวกรองที่คั่นด้วยเครื่องหมายจุลภาคที่แสดงด้วยเครื่องหมายจุด

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


6

นี่คือวิธีแก้ไขปัญหาอื่นตอนนี้ใช้นิพจน์การ แข่งขัน

การกรองแหล่งที่มา
ช่วยให้สามารถควบคุมวิธีการส่งคืนฟิลด์ _source ในทุก Hit

ทดสอบกับ Elastiscsearch เวอร์ชั่น 5.5

คำหลัก"รวมถึง"กำหนดเขตข้อมูลเฉพาะ

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

5

คำขอ REST 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
            }
        }
    ]
}

}


นี่คือการใช้อย่างเต็มรูปแบบสำหรับฉัน
Indithil Indunil

4

ใช่โดยใช้ตัวกรองแหล่งที่มาคุณสามารถทำได้นี่คือ doc -filter source

ตัวอย่างคำขอ

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;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.