2016-12-06 24 views
9

में डुप्लीकेट ढूंढना मैं अपने डेटा में प्रविष्टियों को खोजने की कोशिश कर रहा हूं जो एक से अधिक पहलू में बराबर हैं।Elasticsearch

{ 
    "size": 0, 
    "aggs": { 
    "duplicateFIELD1": { 
     "terms": { 
     "field": "FIELD1", 
     "min_doc_count": 2 }, 
     "aggs": { 
     "duplicateFIELD2": { 
      "terms": { 
      "field": "FIELD2", 
      "min_doc_count": 2 }, 
      "aggs": { 
      "duplicateFIELD3": { 
       "terms": { 
       "field": "FIELD3", 
       "min_doc_count": 2 }, 
       "aggs": { 
       "duplicateFIELD4": { 
        "terms": { 
        "field": "FIELD4", 
        "min_doc_count": 2 }, 
        "aggs": { 
        "duplicate_documents": { 
         "top_hits": {} } } } } } } } } } } } 

यह परिणाम मैं जब कोई डुप्लिकेट इस तरह देखो कुछ पाया जाता है के रूप में एक हद तक काम करता है::

{ 
    "took" : 5, 
    "timed_out" : false, 
    "_shards" : { 
    "total" : 1, 
    "successful" : 1, 
    "failed" : 0 
    }, 
    "hits" : { 
    "total" : 27524067, 
    "max_score" : 0.0, 
    "hits" : [ ] 
    }, 
    "aggregations" : { 
    "duplicateFIELD1" : { 
     "doc_count_error_upper_bound" : 0, 
     "sum_other_doc_count" : 27524027, 
     "buckets" : [ 
     { 
      "key" : <valueFromField1>, 
      "doc_count" : 4, 
      "duplicateFIELD2" : { 
      "doc_count_error_upper_bound" : 0, 
      "sum_other_doc_count" : 0, 
      "buckets" : [ 
       { 
       "key" : <valueFromField2>, 
       "doc_count" : 2, 
       "duplicateFIELD3" : { 
        "doc_count_error_upper_bound" : 0, 
        "sum_other_doc_count" : 0, 
        "buckets" : [ 
        { 
         "key" : <valueFromField3>, 
         "doc_count" : 2, 
         "duplicateFIELD4" : { 
         "doc_count_error_upper_bound" : 0, 
         "sum_other_doc_count" : 0, 
         "buckets" : [ ] 
         } 
        } 
        ] 
       } 
       }, 
       { 
       "key" : <valueFromField2>, 
       "doc_count" : 2, 
       "duplicateFIELD3" : { 
        "doc_count_error_upper_bound" : 0, 
        "sum_other_doc_count" : 0, 
        "buckets" : [ 
        { 
         "key" : <valueFromField3>, 
         "doc_count" : 2, 
         "duplicateFIELD4" : { 
         "doc_count_error_upper_bound" : 0, 
         "sum_other_doc_count" : 0, 
         "buckets" : [ ] 
         } 
        } 
        ] 
       } 
       } 
      ] 
      } 
     }, 
     { 
      "key" : <valueFromField1>, 
      "doc_count" : 4, 
      "duplicateFIELD2" : { 
      "doc_count_error_upper_bound" : 0, 
      "sum_other_doc_count" : 0, 
      "buckets" : [ 
       { 
       "key" : <valueFromField2>, 
       "doc_count" : 2, 
       "duplicateFIELD3" : { 
        "doc_count_error_upper_bound" : 0, 
        "sum_other_doc_count" : 0, 
        "buckets" : [ 
        { 
         "key" : <valueFromField3>, 
         "doc_count" : 2, 
         "duplicateFIELD4" : { 
         "doc_count_error_upper_bound" : 0, 
         "sum_other_doc_count" : 0, 
         "buckets" : [ ] 
         } 
        } 
        ] 
       } 
       }, 
       { 
       "key" : <valueFromField2>, 
       "doc_count" : 2, 
       "duplicateFIELD3" : { 
        "doc_count_error_upper_bound" : 0, 
        "sum_other_doc_count" : 0, 
        "buckets" : [ 
        { 
         "key" : <valueFromField3>, 
         "doc_count" : 2, 
         "duplicateFIELD4" : { 
         "doc_count_error_upper_bound" : 0, 
         "sum_other_doc_count" : 0, 
         "buckets" : [ ] 
         } 
        } 
        ] 
       } 
       } 
      ] 
      } 
     }, 
     ... 

मैं मैं वर्तमान में यह एक जटिल क्वेरी जो एकत्रित घोंसले का उपयोग कर मैं कुछ आउटपुट को छोड़कर जो समान दिखता हूं।

अब मैं इस जटिल गहराई से घनिष्ठ डेटा संरचना के माध्यम से स्कैन कर सकता हूं और यह पता लगा सकता हूं कि इन सभी घोंसले वाली बाल्टी में कोई दस्तावेज़ संग्रहीत नहीं है। लेकिन यह बल्कि बोझिल लगता है। मुझे लगता है कि ऐसा करने का एक बेहतर (अधिक सीधा-आगे) तरीका हो सकता है।

इसके अलावा, अगर मैं चार से अधिक क्षेत्रों की जांच करना चाहता हूं, तो यह घोंसला वाली संरचना बढ़ेगी और बढ़ेगी और बढ़ेगी। तो यह बहुत अच्छी तरह से स्केल नहीं करता है और मैं इससे बचना चाहता हूं।

क्या मैं अपना समाधान सुधार सकता हूं ताकि मुझे डुप्लीकेट वाले सभी दस्तावेजों की एक साधारण सूची मिल सके? (हो सकता है कि वे जो एक-दूसरे के साथ मिलकर एक दूसरे के समूहबद्ध हों।) या क्या एक पूरी तरह से अलग दृष्टिकोण है (जैसे कि एकत्रीकरण के बिना) जिसमें मेरे द्वारा वर्णित दोष नहीं हैं?

संपादित करें: मैं ES here की स्क्रिप्ट सुविधा का उपयोग कर एक दृष्टिकोण मिल गया, लेकिन ES के अपने संस्करण में यह सिर्फ एक त्रुटि संदेश देता है। शायद कोई मुझे बता सकता है कि ईएस 5.0 में इसे कैसे किया जाए? अब तक मेरे परीक्षण काम नहीं कर पाए।

संपादित करें:

{ 
    "size": 0, 
    "aggs": { 
    "duplicateFOO": { 
     "terms": { 
     "script": { 
      "lang": "painless", 
      "inline": "doc['FIELD1'].value + doc['FIELD2'].value + doc['FIELD3'].value + doc['FIELD4'].value" 
     },     
     "min_doc_count": 2 
     }       
    }       
    } 
} 

यह एक में डेटा और परिणाम की बहुत छोटी मात्रा के लिए काम करने लगता है: मैं जो आधुनिक तरीका (भाषा "दर्दरहित") का उपयोग करता है मेरी दृष्टिकोण के लिए एक स्क्रिप्ट का उपयोग करने के लिए एक रास्ता मिल गया डेटा की यथार्थवादी मात्रा के लिए त्रुटि (circuit_breaking_exception: [request] Data too large, data for [<reused_arrays>] would be larger than limit of [6348236390/5.9gb])। इस पर कोई विचार है कि मैं इसे कैसे ठीक कर सकता हूं? संभवतः बड़े आंतरिक बफर या इसी तरह का उपयोग करने के लिए ES की कुछ कॉन्फ़िगरेशन समायोजित करें?


मेरी स्थिति के लिए एक उचित समाधान प्रतीत नहीं होता है जो सामान्य तरीके से घोंसले से बचाता है।

सौभाग्य से मेरे चार क्षेत्रों में से तीन में बहुत सीमित मूल्य सीमा है; पहला केवल 1 या 2 हो सकता है, दूसरा 1, 2, या 3 हो सकता है और तीसरा 1, 2, 3, या 4 हो सकता है। चूंकि ये केवल 24 संयोजन हैं जिन्हें मैं वर्तमान में 24 वें स्थान पर फ़िल्टर करने के साथ जाता हूं एकत्रीकरण लागू करने से पहले डेटा सेट, फिर केवल एक (शेष चौथा क्षेत्र)। इसके बाद मुझे सभी कार्यों को 24 बार लागू करना होगा (एक बार ऊपर वर्णित तीन सीमित क्षेत्रों के प्रत्येक संयोजन के साथ), लेकिन यह एक बार में पूर्ण डेटा सेट को संभालने से कहीं अधिक व्यवहार्य है।

क्वेरी (मैं ई 24 प्रश्नों में से एक।।) मैं अब कुछ इस तरह दिखाई भेजें:

{ 
    "size": 0, 
    "query": { 
    "bool": { 
     "must": [ 
     { "match": { "FIELD1": 2 } }, 
     { "match": { "FIELD2": 3 } }, 
     { "match": { "FIELD3": 4 } } ] } }, 
    "aggs": { 
    "duplicateFIELD4": { 
     "terms": { 
     "field": "FIELD4", 
     "min_doc_count": 2 } } } } 

निश्चित रूप से इस के लिए परिणाम अब और नहीं लगाए गए हैं। लेकिन यह तब नहीं किया जा सकता है जब एक से अधिक फ़ील्ड एक बड़ी सीमा के मनमाना मूल्य रखती हैं।

मुझे यह भी पता चला कि यदि घोंसला करना आवश्यक है, तो सबसे सीमित मूल्य सीमा वाले फ़ील्ड (ई। जी।"1 या 2" जैसे दो मान) सबसे कम होना चाहिए, और सबसे बड़ी मान सीमा वाला सबसे बाहरी होना चाहिए। यह प्रदर्शन में काफी सुधार करता है (लेकिन अभी भी मेरे मामले में पर्याप्त नहीं है)। इसे गलत करने से आप एक अनुपयोगी क्वेरी (घंटों के भीतर कोई प्रतिक्रिया नहीं दे सकते हैं, और आखिरकार सर्वर की ओर से स्मृति से बाहर हो सकते हैं)।

अब मुझे लगता है कि मेरी तरह की समस्या को हल करने के लिए सही ढंग से एकत्र करना महत्वपूर्ण है। एक फ्लैट बाल्टी सूची (जैसा कि मेरे प्रश्न में वर्णित है) रखने के लिए एक स्क्रिप्ट का उपयोग सर्वर को अधिभारित करने के लिए बाध्य है क्योंकि यह किसी भी तरह से कार्य वितरित नहीं कर सकता है। इस मामले में कि कोई भी डबल नहीं मिला है, इसे प्रत्येक दस्तावेज़ के लिए स्मृति में एक बाल्टी पकड़नी है (इसमें केवल एक दस्तावेज़ के साथ)। यहां तक ​​कि अगर कुछ युगल पाए जा सकते हैं, तो यह बड़े डेटा सेट के लिए नहीं किया जा सकता है। यदि कुछ भी संभव नहीं है, तो किसी को डेटा सेट को कृत्रिम रूप से समूहों में विभाजित करने की आवश्यकता होगी। ई जी कोई प्रासंगिक फ़ील्ड से हैश बनाने के द्वारा 16 उप-डेटा सेट बना सकता है और दस्तावेज़ को 16 समूहों में रखने के लिए अंतिम 4 बिट्स का उपयोग कर सकता है। प्रत्येक समूह को अलग से संभाला जा सकता है; युगल इस तकनीक का उपयोग कर एक समूह में गिरने के लिए बाध्य हैं।

लेकिन इन सामान्य विचारों से स्वतंत्र रूप से, ईएस एपीआई को एकत्रीकरण के परिणाम के माध्यम से अंकन करने के लिए कोई साधन प्रदान करना चाहिए। यह दयालु है कि ऐसा कोई विकल्प नहीं है (अभी तक)।

+0

मेरी राय में, आपके दस्तावेज़ों में एक नया क्षेत्र बनाने का सबसे अच्छा और सही तरीका है (बेशक, इसका मतलब डेटा को एक नई अनुक्रमणिका में पुन: अनुक्रमणित करना है) जिसमें उन फ़ील्ड संयोजनों को शामिल करना चाहिए जिन्हें आप ढूंढ रहे हैं। फिर, खोज समय पर आप उस एकल फ़ील्ड पर एकत्र कर सकते हैं। –

+0

यदि आप विभिन्न क्षेत्रों को जोड़ रहे हैं, तो हमेशा उनके बीच कुछ विभाजक जोड़ने के लिए सबसे अच्छा है, इसलिए आप अधिक सुनिश्चित हैं कि एकाधिक फ़ील्ड का विलय फ़ील्ड के किसी अन्य संयोजन के विलय के समान नहीं है।(उदाहरण के लिए 'टेस्ट' + 'आईएनजी' = 'परीक्षण' => 'टेस्ट' + '#' + 'आईएनजी' <> 'परीक्षण') – rvheddeg

उत्तर

0

एक विचार है कि एक Logstash परिदृश्य में काम कर सकते हैं प्रतिलिपि फ़ील्ड का उपयोग किया जाता है:

कॉपी सब एक अलग क्षेत्रों के लिए संयोजन और उन्हें concat: नए क्षेत्र से अधिक

mutate { 
    add_field => { 
    "new_field" => "%{oldfield1} %{oldfield2}" 
    } 
} 

कुल। https://www.elastic.co/guide/en/logstash/current/plugins-filters-mutate.html

add_field सरणी (दूसरों अगर आप प्रलेखन पर देखने करते हैं) का समर्थन करता है, तो मैं नहीं जानता कि:

यहाँ एक नज़र डालें। यदि ऐसा नहीं होता है तो आप कई नए फ़ील्ड जोड़ने और केवल एक फ़ील्ड रखने के लिए विलय का उपयोग करने का प्रयास कर सकते हैं।

यदि आप इसे इंडेक्स समय पर कर सकते हैं तो यह निश्चित रूप से बेहतर होगा।

आप केवल संयोजन (A_B) और सभी क्रमपरिवर्तन (A_B, B_A)

+0

बेशक, और संभवतः आकार के आधार पर हम संभव हो सकते हैं। मेरे मामले में मुझे डर है कि उत्परिवर्तन प्रक्रिया में काफी समय लग सकता है, और यदि मुझे फ़ील्ड के विभिन्न सेट बराबर होने की आवश्यकता है, तो मुझे आपके द्वारा प्रस्तावित नए_फील्ड के कई संस्करण बनाना होगा। यह मेरे मामले में स्मृति समस्या भी हो सकता है: -/ – Alfe

+0

मुझे लगता है कि आपका उत्तर केवल लॉगस्टैश स्थितियों पर लागू होता है। मैं लॉगस्टैश का उपयोग नहीं कर रहा हूं और फिर भी मेरी समस्या को हल करना चाहता हूं ;-) – Alfe

+0

और संयोजनों के साथ पुन: उपयोग करने के बारे में कैसे? यदि आपके पास 10 फ़ील्ड हैं तो आप प्रत्येक फ़ील्ड को 9 गुना अधिक सामान्य सूचकांक करेंगे, जबकि वह फ़ील्ड एक गैर-विश्लेषण क्षेत्र हो सकता है। यदि आप नहीं चाहते हैं कि आप एक स्क्रिप्ट फ़ील्ड पर विचार कर सकें जहां आप उन मान डालते हैं लेकिन प्रदर्शन अनावश्यक अनुक्रमित फ़ील्ड के साथ निश्चित रूप से बेहतर होगा। –

1

आपकी आखिरी दृष्टिकोण सबसे अच्छा एक लगता है की जरूरत है। और तुम update your elasticsearch settings के रूप में निम्नलिखित कर सकते हैं:

indices.breaker.request.limit: "75%" 
indices.breaker.total.limit: "85%" 

मैं 75% को चुना है क्योंकि डिफ़ॉल्ट 60% है और यह अपने elasticsearch में 5.9gb है और आपकी क्वेरी ~6.3gb जो चारों ओर 71.1% अपनी लॉग पर आधारित है बनता जा रहा है।

circuit_breaking_exception: [request] Data too large, data for [<reused_arrays>] would be larger than limit of [6348236390/5.9gb]

और अंत में indices.breaker.total.limitindices.breaker.fielddata.limit से अधिक elasticsearch document के अनुसार होना चाहिए।

+0

पढ़ने के लिए अपना स्वयं का जवाब देखें कि यह पूरा दृष्टिकोण वास्तव में बड़े डेटा सेटों के साथ व्यवहार्य क्यों नहीं है (जैसा कि मुझे अब समझना है), इसलिए ऊपर कुछ तकनीकी सीमाओं को धक्का देना समाधान नहीं है। – Alfe