पहले मैंने अपनी स्कीमा में _id घोषित नहीं किया था, इसलिए प्रत्येक नए सबमिशन में स्वाभाविक रूप से MongoDB ObjectId उत्पन्न होगा क्योंकि यह _id है। हालाँकि, आवश्यकताएं बदल गई हैं और अब _id को String के रूप में नीचे घोषित किया गया है।

var mongoose = require("mongoose");
var Schema = mongoose.Schema;

var MySchema = new Schema({
    _id: {
        type: String,
    },
    schoolID: {
        type: mongoose.Schema.Types.ObjectId, ref: 'School'
    },
    points: {
        type: Number
    },
});
MySchema.index({ schoolID : 1})

module.exports = mongoose.model('Submission', MySchema);

हालाँकि, अब मैं _id का उपयोग करके अपने पहले डाले गए दस्तावेज़ों को बिल्कुल भी नहीं ढूँढ सकता। मैंने कोशिश की

var submissionId = "60654319a8062f684ac8fde4"
Submission.findOne({ _id: mongoose.mongo.ObjectId(submissionId ) })
Submission.findOne({ _id: mongoose.Types.ObjectId(submissionId ) })
Submission.findOne({ _id: mongoose.ObjectId(submissionId ) })

लेकिन यह हमेशा null लौटाएगा। इसलिए जब मैं जांच करने के लिए var mongoose = require('mongoose').set('debug', true); का उपयोग करता हूं, तो यह नीचे प्रदर्शित होगा; कि मेरे उपरोक्त सभी प्रश्न अभी भी String का उपयोग करते हुए मिलेंगे, न कि ObjectId

Mongoose: submission.findOne({ _id: '60654319a8062f684ac8fde4' }, { projection: {} })
2
imin 3 अप्रैल 2021, 17:58

2 जवाब

सबसे बढ़िया उत्तर

समस्या - _id: { type: String,}, नेवला डेटाबेस के लिए एक क्वेरी करने से पहले मूल्य डालेगा, इसलिए आपके मामले में, यह हमेशा एक स्ट्रिंग होगा।

विकल्प 1

अपने पुराने ऑब्जेक्ट आईडी को स्ट्रिंग में कनवर्ट करें क्योंकि आप स्ट्रिंग _id का उपयोग करने की योजना बना रहे हैं, इसलिए इसे लगातार बनाए रखना बेहतर है।

इन आदेशों को खोल से चलाएँ, रोबोमोंगो

यह मौजूदा ObjectId रिकॉर्ड के लिए स्ट्रिंग _id के साथ रिकॉर्ड जोड़ देगा।

db.collection.find({}).toArray() // loop all records
    .forEach(function (c) {
        if (typeof c._id !== 'string') { // check _id is not string
            c._id = c._id.str; db.collection.save(c); // create new record with _id as string value
        }
    });

ObjectId के साथ रिकॉर्ड हटाएं

db.collection.remove({ _id: { $type: 'objectId' } })

विकल्प 2

नेवला कस्टम प्रकार जोड़ें।

https://mongoosejs.com/docs/customschematypes.html

class StringOrObjectId extends mongoose.SchemaType {
  constructor(key, options) {
    super(key, options, 'StringOrObjectId');
  }

  convertToObjectId(v) {
    const checkForHexRegExp = new RegExp("^[0-9a-fA-F]{24}$");
    let _val;
    try {
      if (checkForHexRegExp.test(v)) {
        _val = mongoose.Types.ObjectId(v);
        return _val;
      }
    } catch (e) {
      console.log(e);
    }
  }

  convertToString(v) {
    let _val = v;
    try {
      if(_.isString(_val)) return _val;
      if(_.isNumber(_val)) return _.toString(_val);
    } catch (e) {
      console.log(e);
    }
  }

  cast(val) {
    const objectIdVal = this.convertToObjectId(val);
    if (objectIdVal) return objectIdVal;

    const stringVal = this.convertToString(val)
    if (stringVal) return stringVal;

    throw new Error('StringOrObjectId: ' + val +
        ' Nor string nor ObjectId');
  }
}

mongoose.Schema.Types.StringOrObjectId = StringOrObjectId;

var MySchema = new Schema({
    _id: {
        type: StringOrObjectId, // custom type here
    },
    schoolID: {
        type: mongoose.Schema.Types.ObjectId, ref: 'School'
    },
    points: {
        type: Number
    },
});

जिज्ञासा

Submission.findOne({ _id: submissionId }); // it will cast ObjectId or String or throw error

कमियां

  • यदि आपकी _id प्रकार की स्ट्रिंग 60516ae1ef682d2804a2fa72 मान्य ObjectId की तरह है तो यह ObjectId में बदल जाएगी जो रिकॉर्ड से मेल नहीं खाएगा।

नोट - यह एक मोटा वर्ग है StringOrObjectId उचित जांच जोड़ें और ठीक से परीक्षण करें।


विकल्प -3

आसान तरीका - mongoose.Mixed का उपयोग करें https://mongoosejs.com/docs/schematypes.html#mixed

https://mongoosejs.com/docs/api.html#mongoose_Mongoose-Mixed

cont MySchema = new Schema({
    _id: {
        type: mongoose.Mixed,
    },
    schoolID: {
        type: mongoose.Schema.Types.ObjectId, ref: 'School'
    },
    points: {
        type: Number
    },
});
2
Tushar Gupta - curioustushar 3 अप्रैल 2021, 20:09

नेवले में इस स्थिति को संभालने का कोई सीधा तरीका नहीं है,

नेवला कमांड भेजे जाने से पहले मॉडल के स्कीमा से मेल खाने के लिए फिल्टर को कास्ट करता है। Mongoose कैसे फ़िल्टर करता है, इस बारे में अधिक जानकारी के लिए क्वेरी कास्टिंग ट्यूटोरियल देखें।

आप कस्टम स्कीमा प्रकार आज़मा सकते हैं,

class StrOrObjId extends mongoose.SchemaType {
    constructor(key, options) {
        super(key, options, 'StrOrObjId');
    }
    cast(val) {
        if (typeof val !== 'string' && !mongoose.Types.ObjectId.isValid(val)) {
            throw new Error('StrOrObjId: ' + val + ' must be a String or ObjectId');
        }
        return val;
    }
}
// Don't forget to add `StrOrObjId` to the type registry
mongoose.Schema.Types.StrOrObjId = StrOrObjId;

_id फ़ील्ड में उस प्रकार का उपयोग करें,

var MySchema = new Schema({
    _id: {
        type: StrOrObjId,
    },
    schoolID: {
        type: mongoose.Schema.Types.ObjectId, ref: 'School'
    },
    points: {
        type: Number
    }
});
2
turivishal 3 अप्रैल 2021, 21:19