MongoDB
 sql >> डेटाबेस >  >> NoSQL >> MongoDB

MongoDB दस्तावेज़ को अनमर्शलिंग करते समय नल को कैसे अनदेखा करें?

समस्या यह है कि वर्तमान बीएसओएन कोडेक्स एन्कोडिंग/डिकोडिंग string का समर्थन नहीं करते हैं में / से null

इसे संभालने का एक तरीका string . के लिए एक कस्टम डिकोडर बनाना है टाइप करें जिसमें हम null handle को हैंडल करते हैं मान:हम केवल खाली स्ट्रिंग का उपयोग करते हैं (और अधिक महत्वपूर्ण बात यह है कि त्रुटि की रिपोर्ट न करें)।

कस्टम डिकोडर का वर्णन bsoncodec.ValueDecoder . प्रकार से किया जाता है . उन्हें bsoncodec.Registry . पर पंजीकृत किया जा सकता है , एक bsoncodec.RegistryBuilder . का उपयोग करके उदाहरण के लिए।

रजिस्ट्रियों को कई स्तरों पर सेट/लागू किया जा सकता है, यहां तक ​​कि संपूर्ण mongo.Client . पर भी , या किसी mongo.Database . पर या सिर्फ एक mongo.Collection . के लिए , उन्हें प्राप्त करते समय, उनके विकल्पों के भाग के रूप में, उदा. options.ClientOptions.SetRegistry()

सबसे पहले देखते हैं कि हम string . के लिए यह कैसे कर सकते हैं , और आगे हम देखेंगे कि किसी भी प्रकार के समाधान को कैसे सुधारें/सामान्यीकृत करें।

<एच3>1. हैंडलिंग null तार

सबसे पहले चीज़ें, आइए एक कस्टम स्ट्रिंग डिकोडर बनाते हैं जो एक null . को बदल सकता है एक (एन खाली) स्ट्रिंग में:

import (
    "go.mongodb.org/mongo-driver/bson/bsoncodec"
    "go.mongodb.org/mongo-driver/bson/bsonrw"
    "go.mongodb.org/mongo-driver/bson/bsontype"
)

type nullawareStrDecoder struct{}

func (nullawareStrDecoder) DecodeValue(dctx bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
    if !val.CanSet() || val.Kind() != reflect.String {
        return errors.New("bad type or not settable")
    }
    var str string
    var err error
    switch vr.Type() {
    case bsontype.String:
        if str, err = vr.ReadString(); err != nil {
            return err
        }
    case bsontype.Null: // THIS IS THE MISSING PIECE TO HANDLE NULL!
        if err = vr.ReadNull(); err != nil {
            return err
        }
    default:
        return fmt.Errorf("cannot decode %v into a string type", vr.Type())
    }

    val.SetString(str)
    return nil
}

ठीक है, और अब देखते हैं कि इस कस्टम स्ट्रिंग डिकोडर का उपयोग mongo.Client में कैसे करें :

clientOpts := options.Client().
    ApplyURI("mongodb://localhost:27017/").
    SetRegistry(
        bson.NewRegistryBuilder().
            RegisterDecoder(reflect.TypeOf(""), nullawareStrDecoder{}).
            Build(),
    )
client, err := mongo.Connect(ctx, clientOpts)

अब से, इस client का उपयोग करते हुए , जब भी आप परिणामों को string . में डिकोड करते हैं मान, यह पंजीकृत nullawareStrDecoder डिकोडर को रूपांतरण को संभालने के लिए बुलाया जाएगा, जो bson null को स्वीकार करता है मान और गो खाली स्ट्रिंग सेट करता है ""

लेकिन हम बेहतर कर सकते हैं... आगे पढ़ें...

<एच3>2. हैंडलिंग null किसी भी प्रकार के मान:"टाइप-न्यूट्रल" नल-अवेयर डिकोडर

एक तरीका यह होगा कि एक अलग, कस्टम डिकोडर बनाया जाए और इसे प्रत्येक प्रकार के लिए पंजीकृत किया जाए जिसे हम संभालना चाहते हैं। ऐसा लगता है कि यह बहुत काम है।

इसके बजाय हम जो कर सकते हैं (और करना चाहिए) वह एक एकल, "टाइप-न्यूट्रल" कस्टम डिकोडर बनाना है जो केवल null को हैंडल करता है। s, और यदि BSON मान null नहीं है , गैर को संभालने के लिए डिफ़ॉल्ट डिकोडर को कॉल करना चाहिए-null मूल्य।

यह आश्चर्यजनक रूप से सरल है:

type nullawareDecoder struct {
    defDecoder bsoncodec.ValueDecoder
    zeroValue  reflect.Value
}

func (d *nullawareDecoder) DecodeValue(dctx bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
    if vr.Type() != bsontype.Null {
        return d.defDecoder.DecodeValue(dctx, vr, val)
    }

    if !val.CanSet() {
        return errors.New("value not settable")
    }
    if err := vr.ReadNull(); err != nil {
        return err
    }
    // Set the zero value of val's type:
    val.Set(d.zeroValue)
    return nil
}

हमें बस यह पता लगाना है कि nullawareDecoder.defDecoder के लिए क्या उपयोग करना है . इसके लिए हम डिफ़ॉल्ट रजिस्ट्री का उपयोग कर सकते हैं:bson.DefaultRegistry , हम अलग-अलग प्रकारों के लिए डिफ़ॉल्ट डिकोडर देख सकते हैं। कूल।

तो अब हम जो करते हैं वह हमारे nullawareDecoder . का एक मान पंजीकृत करता है सभी प्रकार के लिए हम null handle को हैंडल करना चाहते हैं एस के लिए। यह इतना मुश्किल नही है। हम केवल उन प्रकारों (या उन प्रकारों के मान) को सूचीबद्ध करते हैं जिनके लिए हम चाहते हैं, और हम एक साधारण लूप के साथ सभी का ध्यान रख सकते हैं:

customValues := []interface{}{
    "",       // string
    int(0),   // int
    int32(0), // int32
}

rb := bson.NewRegistryBuilder()
for _, v := range customValues {
    t := reflect.TypeOf(v)
    defDecoder, err := bson.DefaultRegistry.LookupDecoder(t)
    if err != nil {
        panic(err)
    }
    rb.RegisterDecoder(t, &nullawareDecoder{defDecoder, reflect.Zero(t)})
}

clientOpts := options.Client().
    ApplyURI("mongodb://localhost:27017/").
    SetRegistry(rb.Build())
client, err := mongo.Connect(ctx, clientOpts)

ऊपर के उदाहरण में मैंने string . के लिए नल-जागरूक डिकोडर पंजीकृत किए हैं , int और int32 , लेकिन आप इस सूची को अपनी पसंद के अनुसार बढ़ा सकते हैं, बस वांछित प्रकारों के मान customValues में जोड़ें ऊपर का टुकड़ा।



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. यदि दस्तावेज़ मौजूद है तो MongoDB सही है

  2. मोंगोडब नेवला में E11000 डुप्लिकेट कुंजी त्रुटि सूचकांक

  3. नेवला पासवर्ड हैशिंग

  4. MongoDB में ढूँढें () और findOne () तरीके अलग-अलग परिणाम दिखा रहे हैं

  5. छवियों को MongoDB डेटाबेस में संग्रहीत करें