2016-06-24 10 views
8

मैं ईएस के साथ खेल रहा हूं यह समझने के लिए कि क्या यह मेरे अधिकांश परिदृश्यों को कवर कर सकता है। मैं उस बिंदु पर हूं जहां मैं सोच रहा हूं कि SQL में बहुत सरल कुछ निश्चित परिणामों तक कैसे पहुंचे।लोचदार खोज एसक्यूएल जैसे सबक्वायरी एग्रीगेशन

यह उदाहरण

लोचदार में है मैं इस दस्तावेज

{ "Id": 1, "Fruit": "Banana", "BoughtInStore"="Jungle", "BoughtDate"=20160101, "BestBeforeDate": 20160102, "BiteBy":"John"} 
{ "Id": 2, "Fruit": "Banana", "BoughtInStore"="Jungle", "BoughtDate"=20160102, "BestBeforeDate": 20160104, "BiteBy":"Mat"} 
{ "Id": 3, "Fruit": "Banana", "BoughtInStore"="Jungle", "BoughtDate"=20160103, "BestBeforeDate": 20160105, "BiteBy":"Mark"} 
{ "Id": 4, "Fruit": "Banana", "BoughtInStore"="Jungle", "BoughtDate"=20160104, "BestBeforeDate": 20160201, "BiteBy":"Simon"} 
{ "Id": 5, "Fruit": "Orange", "BoughtInStore"="Jungle", "BoughtDate"=20160112, "BestBeforeDate": 20160112, "BiteBy":"John"} 
{ "Id": 6, "Fruit": "Orange", "BoughtInStore"="Jungle", "BoughtDate"=20160114, "BestBeforeDate": 20160116, "BiteBy":"Mark"} 
{ "Id": 7, "Fruit": "Orange", "BoughtInStore"="Jungle", "BoughtDate"=20160120, "BestBeforeDate": 20160121, "BiteBy":"Simon"} 
{ "Id": 8, "Fruit": "Kiwi", "BoughtInStore"="Shop", "BoughtDate"=20160121, "BestBeforeDate": 20160121, "BiteBy":"Mark"} 
{ "Id": 8, "Fruit": "Kiwi", "BoughtInStore"="Jungle", "BoughtDate"=20160121, "BestBeforeDate": 20160121, "BiteBy":"Simon"} 

साथ एक सूचकांक है मुझे पता है कि कितने फल अलग दुकान लोगों में खरीदा एसक्यूएल मैं में विशिष्ट दिनांक सीमा में काट चाहते हैं, तो इस तरह

SELECT 
    COUNT(DISTINCT kpi.Fruit) as Fruits, 
    kpi.BoughtInStore, 
    kpi.BiteBy 
FROM 
    (
     SELECT f1.Fruit, f1.BoughtInStore, f1.BiteBy 
     FROM FruitsTable f1 
     WHERE f1.BoughtDate = (
      SELECT MAX(f2.BoughtDate) 
      FROM FruitsTable f2 
      WHERE f1.Fruit = f2.Fruit 
      and f2.BoughtDate between 20160101 and 20160131 
      and (f2.BestBeforeDate between 20160101 and 20160131) 
     ) 
    ) kpi 
GROUP BY kpi.BoughtInStore, kpi.ByteBy 

परिणाम कुछ लिखो इस

की तरह कुछ है
{ "Fruits": 1, "BoughtInStore": "Jungle", "BiteBy"="Mark"} 
{ "Fruits": 1, "BoughtInStore": "Shop", "BiteBy"="Mark"} 
{ "Fruits": 2, "BoughtInStore": "Jungle", "BiteBy"="Simon"} 

क्या आपको पता है कि मैं एलास्टिक में एकत्रीकरण के साथ एक ही परिणाम तक कैसे पहुंच सकता हूं?

कुछ शब्दों में समस्याओं मैं लोचदार में सामना करना पड़ रहा हैं:

  1. तैयारी कैसे एकत्रीकरण
  2. कैसे (इस उदाहरण में प्रत्येक फल प्रति रेंज में नवीनतम पंक्ति की तरह) से पहले डेटा का एक subsed कई क्षेत्रों से समूह के परिणाम को

के रूप में मैं समझता हूँ कि वहाँ कोई रास्ता नहीं एक ही क्वेरी के फिल्टर में एकत्रीकरण परिणाम उल्लेख करने के लिए है कि आप

उत्तर

2

धन्यवाद। तो अगर आप एक क्वेरी के साथ पहेली का ही हिस्सा हल कर सकते हैं:

GET /purchases/fruits/_search 
{ 
    "query": { 
    "filtered":{ 
     "filter": { 
     "range": { 
      "BoughtDate": { 
      "gte": "2015-01-01", //assuming you have right mapping for dates 
      "lte": "2016-03-01" 
      } 
     } 
     } 
    } 
    }, 
    "sort": { "BoughtDate": { "order": "desc" }}, 
    "aggs": { 
    "byBoughtDate": { 
     "terms": { 
     "field": "BoughtDate", 
     "order" : { "_term" : "desc" } 
     }, 
     "aggs": { 
     "distinctCount": { 
      "cardinality": { 
      "field": "Fruit" 
      } 
     } 
     } 
    } 
    } 
} 

तो तुम तिथियों की सीमा के भीतर सभी दस्तावेजों होगा, और आप के लिए एकत्रित बाल्टी मायने रखता है, अवधि के अनुसार क्रमबद्ध होगा, तो अधिकतम तारीख हो जाएगा सबसे ऊपर। ग्राहक इस पहली बाल्टी (दोनों गिनती और मूल्य) को पार्स कर सकते हैं, और फिर इस दिनांक मूल्य के लिए दस्तावेज़ ले सकते हैं। विशिष्ट फल गणना के लिए आप केवल नेस्टेड कार्डिनालिटी एकत्रीकरण का उपयोग करें।

हाँ, क्वेरी और अधिक जानकारी की तुलना में आप की जरूरत देता है, लेकिन यह जीवन :)

1

स्वाभाविक रूप से वहाँ Elasticsearch डीएसएल के लिए एसक्यूएल से कोई सीधा रास्ता है, लेकिन वहाँ कुछ बहुत सामान्य सह-संबंध है।

स्टार्टर्स के लिए, GROUP BY/HAVING एकत्रीकरण के लिए नीचे आने वाला है। क्वेरी डीएसएल द्वारा सामान्य क्वेरी अर्थशास्त्र को आम तौर पर कवर किया जा सकता है (और अधिक)।

तैयारी कैसे डेटा की एक subsed एकत्रीकरण से पहले

तो, आप एक तरह से दो अलग-अलग बातों के लिए पूछ रहे हैं (इस उदाहरण प्रत्येक फल प्रति रेंज में नवीनतम पंक्ति में की तरह)।

कैसे एक एकत्रीकरण

से पहले डेटा के subsed तैयार इस क्वेरी चरण है।

आप तकनीकी रूप से यह पूछ रहे हैं इस उदाहरण का जवाब पाने के लिए एकत्र करने के लिए (इस उदाहरण प्रत्येक फल प्रति रेंज में नवीनतम पंक्ति में की तरह): नहीं एक सामान्य क्वेरी। आपके उदाहरण में, आप इसे पाने के लिए ग्रुप बाय का उपयोग कर प्रभावी रूप से प्राप्त करने के लिए MAX कर रहे हैं।

से अधिक फ़ील्ड

यह निर्भर करता है के द्वारा समूह के परिणाम कैसे। क्या आप उन्हें टायर करना चाहते हैं (आमतौर पर, हाँ) या आप उन्हें एक साथ चाहते हैं।

यदि आप उन्हें टायर करना चाहते हैं, तो आप जो चाहते हैं उसे प्राप्त करने के लिए बस उप-एकत्रीकरण का उपयोग करें। यदि आप उन्हें संयुक्त करना चाहते हैं, तो आप आम तौर पर विभिन्न समूहों के लिए filters एकत्रीकरण का उपयोग करते हैं।

इसे एक साथ वापस रखकर: आप एक निश्चित फ़िल्टर की गई तिथि सीमा के अनुसार सबसे हाल ही की खरीद, प्रति फल चाहते हैं। तिथि सीमाओं बस सामान्य प्रश्नों के लिए/फिल्टर कर रहे हैं:

{ 
    "query": { 
    "bool": { 
     "filter": [ 
     { 
      "range": { 
      "BoughtDate": { 
       "gte": "2016-01-01", 
       "lte": "2016-01-31" 
      } 
      } 
     }, 
     { 
      "range": { 
      "BestBeforeDate": { 
       "gte": "2016-01-01", 
       "lte": "2016-01-31" 
      } 
      } 
     } 
     ] 
    } 
    } 
} 
इसी के साथ

, कोई दस्तावेज़ अनुरोध है कि (प्रभावी रूप से एक AND) दोनों क्षेत्रों के लिए उन तिथि सीमाओं के भीतर नहीं है में शामिल किया जाएगा। क्योंकि मैंने एक फ़िल्टर का उपयोग किया, यह असुरक्षित और कैशबल है।

अब, आपको शेष जानकारी प्राप्त करने के लिए एकत्र करना शुरू करना होगा। आइए मान लें कि हम जो देख रहे हैं उसे सरल बनाने के लिए उपरोक्त फ़िल्टर का उपयोग करके दस्तावेजों को फ़िल्टर किया गया है। हम इसे अंत में जोड़ देंगे।

{ 
    "size": 0, 
    "aggs": { 
    "group_by_date": { 
     "date_histogram": { 
     "field": "BoughtDate", 
     "interval": "day", 
     "min_doc_count": 1 
     }, 
     "aggs": { 
     "group_by_store": { 
      "terms": { 
      "field": "BoughtInStore" 
      }, 
      "aggs": { 
      "group_by_person": { 
       "terms": { 
       "field": "BiteBy" 
       } 
      } 
      } 
     } 
     } 
    } 
    } 
} 

आप क्योंकि आप वास्तव में हिट के बारे में परवाह नहीं है शीर्ष स्तर पर "size" : 0 चाहते हैं। आप केवल समेकित परिणाम चाहते हैं।

आपका पहला एकत्रीकरण वास्तव में सबसे हाल की तारीख द्वारा समूहीकृत था। मैंने इसे थोड़ा और यथार्थवादी बनाने के लिए थोड़ा बदल दिया (प्रत्येक दिन), लेकिन यह प्रभावी रूप से वही है। जिस तरह से आप MAX का उपयोग करते हैं, हम समेकन "size": 1 के साथ उपयोग कर सकते हैं, लेकिन यह truer है कि आप दिनांक (और संभवतः समय!) में शामिल होने पर इसे कैसे करना चाहते हैं। मैंने उन मिलान दस्तावेजों में दिनों को अनदेखा करने के लिए भी कहा जिनके पास कोई डेटा नहीं है (क्योंकि यह शुरुआत से अंत तक जा रहा है, हम वास्तव में उन दिनों की परवाह नहीं करते हैं)।

यदि आप वास्तव में केवल अंतिम दिन चाहते थे, तो आप अधिकतम बाल्टी को छोड़कर सबकुछ छोड़ने के लिए पाइपलाइन एकत्रीकरण का उपयोग कर सकते हैं, लेकिन इस प्रकार के अनुरोध का यथार्थवादी उपयोग पूर्ण दिनांक सीमा चाहता है।

तो, फिर हम स्टोर द्वारा समूहबद्ध करना जारी रखते हैं, जो आप चाहते हैं। फिर, हम व्यक्ति द्वारा उप-समूह (BiteBy)। यह आपको गिनती से गिनती देगा।

यह सब वापस एक साथ लाना:

{ 
    "size": 0, 
    "query": { 
    "bool": { 
     "filter": [ 
     { 
      "range": { 
      "BoughtDate": { 
       "gte": "2016-01-01", 
       "lte": "2016-01-31" 
      } 
      } 
     }, 
     { 
      "range": { 
      "BestBeforeDate": { 
       "gte": "2016-01-01", 
       "lte": "2016-01-31" 
      } 
      } 
     } 
     ] 
    } 
    }, 
    "aggs": { 
    "group_by_date": { 
     "date_histogram": { 
     "field": "BoughtDate", 
     "interval": "day", 
     "min_doc_count": 1 
     }, 
     "aggs": { 
     "group_by_store": { 
      "terms": { 
      "field": "BoughtInStore" 
      }, 
      "aggs": { 
      "group_by_person": { 
       "terms": { 
       "field": "BiteBy" 
       } 
      } 
      } 
     } 
     } 
    } 
    } 
} 

नोट: यहाँ मैं डेटा कैसे अनुक्रमित है।

PUT /grocery/store/_bulk 
{"index":{"_id":"1"}} 
{"Fruit":"Banana","BoughtInStore":"Jungle","BoughtDate":"2016-01-01","BestBeforeDate":"2016-01-02","BiteBy":"John"} 
{"index":{"_id":"2"}} 
{"Fruit":"Banana","BoughtInStore":"Jungle","BoughtDate":"2016-01-02","BestBeforeDate":"2016-01-04","BiteBy":"Mat"} 
{"index":{"_id":"3"}} 
{"Fruit":"Banana","BoughtInStore":"Jungle","BoughtDate":"2016-01-03","BestBeforeDate":"2016-01-05","BiteBy":"Mark"} 
{"index":{"_id":"4"}} 
{"Fruit":"Banana","BoughtInStore":"Jungle","BoughtDate":"2016-01-04","BestBeforeDate":"2016-02-01","BiteBy":"Simon"} 
{"index":{"_id":"5"}} 
{"Fruit":"Orange","BoughtInStore":"Jungle","BoughtDate":"2016-01-12","BestBeforeDate":"2016-01-12","BiteBy":"John"} 
{"index":{"_id":"6"}} 
{"Fruit":"Orange","BoughtInStore":"Jungle","BoughtDate":"2016-01-14","BestBeforeDate":"2016-01-16","BiteBy":"Mark"} 
{"index":{"_id":"7"}} 
{"Fruit":"Orange","BoughtInStore":"Jungle","BoughtDate":"2016-01-20","BestBeforeDate":"2016-01-21","BiteBy":"Simon"} 
{"index":{"_id":"8"}} 
{"Fruit":"Kiwi","BoughtInStore":"Shop","BoughtDate":"2016-01-21","BestBeforeDate":"2016-01-21","BiteBy":"Mark"} 
{"index":{"_id":"9"}} 
{"Fruit":"Kiwi","BoughtInStore":"Jungle","BoughtDate":"2016-01-21","BestBeforeDate":"2016-01-21","BiteBy":"Simon"} 

यह महत्वपूर्ण कि आपके स्ट्रिंग मान पर इकट्ठा करना चाहते हैं (दुकान और व्यक्ति) not_analyzedstring रों (ईएस में keyword 5.0) कर रहे हैं! अन्यथा यह फ़ील्डडाटा कहलाता है और यह अच्छी बात नहीं है।

मैपिंग ES 1.x में इस प्रकार दिखाई देगा/ES 2.x:

PUT /grocery 
{ 
    "settings": { 
    "number_of_shards": 1 
    }, 
    "mappings": { 
    "store": { 
     "properties": { 
     "Fruit": { 
      "type": "string", 
      "index": "not_analyzed" 
     }, 
     "BoughtInStore": { 
      "type": "string", 
      "index": "not_analyzed" 
     }, 
     "BiteBy": { 
      "type": "string", 
      "index": "not_analyzed" 
     }, 
     "BestBeforeDate": { 
      "type": "date" 
     }, 
     "BoughtDate": { 
      "type": "date" 
     } 
     } 
    } 
    } 
} 
इस के

सभी एक साथ हैं, और आप के रूप में जवाब पाने: अभी

{ 
    "took": 8, 
    "timed_out": false, 
    "_shards": { 
    "total": 1, 
    "successful": 1, 
    "failed": 0 
    }, 
    "hits": { 
    "total": 8, 
    "max_score": 0, 
    "hits": [] 
    }, 
    "aggregations": { 
    "group_by_date": { 
     "buckets": [ 
     { 
      "key_as_string": "2016-01-01T00:00:00.000Z", 
      "key": 1451606400000, 
      "doc_count": 1, 
      "group_by_store": { 
      "doc_count_error_upper_bound": 0, 
      "sum_other_doc_count": 0, 
      "buckets": [ 
       { 
       "key": "Jungle", 
       "doc_count": 1, 
       "group_by_person": { 
        "doc_count_error_upper_bound": 0, 
        "sum_other_doc_count": 0, 
        "buckets": [ 
        { 
         "key": "John", 
         "doc_count": 1 
        } 
        ] 
       } 
       } 
      ] 
      } 
     }, 
     { 
      "key_as_string": "2016-01-02T00:00:00.000Z", 
      "key": 1451692800000, 
      "doc_count": 1, 
      "group_by_store": { 
      "doc_count_error_upper_bound": 0, 
      "sum_other_doc_count": 0, 
      "buckets": [ 
       { 
       "key": "Jungle", 
       "doc_count": 1, 
       "group_by_person": { 
        "doc_count_error_upper_bound": 0, 
        "sum_other_doc_count": 0, 
        "buckets": [ 
        { 
         "key": "Mat", 
         "doc_count": 1 
        } 
        ] 
       } 
       } 
      ] 
      } 
     }, 
     { 
      "key_as_string": "2016-01-03T00:00:00.000Z", 
      "key": 1451779200000, 
      "doc_count": 1, 
      "group_by_store": { 
      "doc_count_error_upper_bound": 0, 
      "sum_other_doc_count": 0, 
      "buckets": [ 
       { 
       "key": "Jungle", 
       "doc_count": 1, 
       "group_by_person": { 
        "doc_count_error_upper_bound": 0, 
        "sum_other_doc_count": 0, 
        "buckets": [ 
        { 
         "key": "Mark", 
         "doc_count": 1 
        } 
        ] 
       } 
       } 
      ] 
      } 
     }, 
     { 
      "key_as_string": "2016-01-12T00:00:00.000Z", 
      "key": 1452556800000, 
      "doc_count": 1, 
      "group_by_store": { 
      "doc_count_error_upper_bound": 0, 
      "sum_other_doc_count": 0, 
      "buckets": [ 
       { 
       "key": "Jungle", 
       "doc_count": 1, 
       "group_by_person": { 
        "doc_count_error_upper_bound": 0, 
        "sum_other_doc_count": 0, 
        "buckets": [ 
        { 
         "key": "John", 
         "doc_count": 1 
        } 
        ] 
       } 
       } 
      ] 
      } 
     }, 
     { 
      "key_as_string": "2016-01-14T00:00:00.000Z", 
      "key": 1452729600000, 
      "doc_count": 1, 
      "group_by_store": { 
      "doc_count_error_upper_bound": 0, 
      "sum_other_doc_count": 0, 
      "buckets": [ 
       { 
       "key": "Jungle", 
       "doc_count": 1, 
       "group_by_person": { 
        "doc_count_error_upper_bound": 0, 
        "sum_other_doc_count": 0, 
        "buckets": [ 
        { 
         "key": "Mark", 
         "doc_count": 1 
        } 
        ] 
       } 
       } 
      ] 
      } 
     }, 
     { 
      "key_as_string": "2016-01-20T00:00:00.000Z", 
      "key": 1453248000000, 
      "doc_count": 1, 
      "group_by_store": { 
      "doc_count_error_upper_bound": 0, 
      "sum_other_doc_count": 0, 
      "buckets": [ 
       { 
       "key": "Jungle", 
       "doc_count": 1, 
       "group_by_person": { 
        "doc_count_error_upper_bound": 0, 
        "sum_other_doc_count": 0, 
        "buckets": [ 
        { 
         "key": "Simon", 
         "doc_count": 1 
        } 
        ] 
       } 
       } 
      ] 
      } 
     }, 
     { 
      "key_as_string": "2016-01-21T00:00:00.000Z", 
      "key": 1453334400000, 
      "doc_count": 2, 
      "group_by_store": { 
      "doc_count_error_upper_bound": 0, 
      "sum_other_doc_count": 0, 
      "buckets": [ 
       { 
       "key": "Jungle", 
       "doc_count": 1, 
       "group_by_person": { 
        "doc_count_error_upper_bound": 0, 
        "sum_other_doc_count": 0, 
        "buckets": [ 
        { 
         "key": "Simon", 
         "doc_count": 1 
        } 
        ] 
       } 
       }, 
       { 
       "key": "Shop", 
       "doc_count": 1, 
       "group_by_person": { 
        "doc_count_error_upper_bound": 0, 
        "sum_other_doc_count": 0, 
        "buckets": [ 
        { 
         "key": "Mark", 
         "doc_count": 1 
        } 
        ] 
       } 
       } 
      ] 
      } 
     } 
     ] 
    } 
    } 
} 
+0

के रूप में , अधिकतम तिथि तक सीमित करने के लिए बाल्टी एकत्रीकरण के साथ मेरा छोटा ध्यान दिया गया कार्य 'date_histogram' के साथ काम नहीं करेगा। विडंबना यह है कि अगर मैं मूल रूप से दिखाए गए नंबरों के रूप में मानों को छोड़ देता हूं तो यह काम करेगा। – pickypg

संबंधित मुद्दे