Mongoose: يتم حفظ المصفوفة الفارغة عندما تشير الخاصية إلى مخطط

تم إنشاؤها على ٦ فبراير ٢٠١٣  ·  39تعليقات  ·  مصدر: Automattic/mongoose

var FooSchema = new Schema({});
var Foo = mongoose.model("Foo", FooSchema);
var BarSchema = new Schema({
    foos: [Foo.schema]
});
var Bar = mongoose.model("Bar", BarSchema);

var b = new Bar();
b.save();

سيؤدي ذلك إلى إنشاء مصفوفة فارغة من b.foos بدلاً من ترك الخاصية غير محددة.

enhancement

التعليق الأكثر فائدة

antonioaltamura لقد نسيت هذه المسألة ، أدناه يعمل في النمس 4.6:

const CollectionSchema = new Schema({
 field1: { type: [String], default: void 0 }, // <-- override the array default to be undefined
});

const Collection = mongoose.model('test', CollectionSchema);

Collection.create({}).
  then(doc => { console.log(doc); return doc; }).
  then(() => { process.exit(0); });

ال 39 كومينتر

هذا حسب التصميم. يتم حفظ جميع القيم الافتراضية بحيث يكون عرض تطبيقات النمس للوثيقة مطابقًا لعرض التطبيقات غير النمس.

حسنًا ، كيف أجعل القيمة الافتراضية فارغة؟ ؛-) حالة الاستخدام هنا هي أنه من المكلف في المونغو طلب جميع نقود البار التي تحتوي على فووس فارغة. لا بد لي من إضافة خاصية أخرى لتتبع تلك الحالة ، الأمر الذي يزيد من تعقيد الكود الخاص بي.

أرى. سيتيح لك ذلك تخطي حفظ ملفات foos الفارغة في مستندات جديدة:

BarSchema.pre('save', function (next) {
  if (this.isNew && 0 === this.foos.length) {
    this.foos = undefined;                                                                                                                                   
  }
  next();
})

حلو. هذا عمل جيد بما يكفي بالنسبة لي.

هل لا يزال من المفترض أن يعمل هذا الحل البديل؟ (النمس 3.8.3 هنا)

ماثيومج: لا يعمل معي (3.8.15)

نعم ، أعتقد أن هذه المسألة تستحق بعض الاهتمام. (إنها صغيرة جدًا ، لكن
أنا مهتم باستخدام pre لأشياء أخرى :))

يوم الاثنين ، 25 آب (أغسطس) 2014 الساعة 4:49 مساءً ، ماتيو إم جوسلين <
[email protected]> كتب:

ربما ينبغي أن أفتح عددًا جديدًا حتى يتم ملاحظته؟

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/LearnBoost/mongoose/issues/1335#issuecomment -53328195
.

+1
ما قبل العمل حول لا يعمل ل 3.8.15
أعتقد أن البديل الوحيد هو أن يكون لديك قيمة فارغة أو خطأ لتبسيط الاستعلام ولكن هذا أيضًا يضيف بعض البايت ويكون له تأثير كبير على قاعدة البيانات الكبيرة.

        this.foos = null;

@ gaurang171Nepoxx هل يمكنكم أن حالة الاختبار )

لا تزال هذه مشكلة بالنسبة لي باستخدام 4.0.1.

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');

var barSchema = new mongoose.Schema({
  baz: String
});

var fooSchema = new mongoose.Schema({
  bars: [barSchema]
});

var Foo = mongoose.model('Foo', fooSchema);

var foo = new Foo();
console.log(foo); // { _id: 55256e20e3c38434687034fb, bars: [] }

foo.save(function(err, foo2) {
  console.log(foo2); // { __v: 0, _id: 55256e20e3c38434687034fb, bars: [] }

  foo2.bars = undefined;
  foo2.save(function(err, foo3) {
    console.log(foo3); // { __v: 0, _id: 55256e20e3c38434687034fb, bars: undefined }

    Foo.findOne({ _id: foo3._id }, function(err, foo4) {
      console.log(foo4); // { _id: 55256e20e3c38434687034fb, __v: 0, bars: [] }

      mongoose.disconnect();
    });
  });
});

viking لم يتم "إصلاحها" أبدًا. تم توفير حل بديل . يجب عليك اختبار لمعرفة ما إذا كان هذا الحل لا يزال يعمل نظرًا لوجود معلومات متضاربة حول ذلك. =)

لدي بالفعل حل بديل في المكان. أنا مهتم بمعرفة ما إذا كان هذا السلوك سيتغير أم لا.

عذرًا ، لم تقل أنك تريد معرفة ما إذا كان السلوك سيتغير أم لا.

لست متأكدًا في الواقع من سبب إعادة فتح هذه المشكلة بواسطة @ vkarpov15 ، والتي تتساءل عما إذا كان هذا السلوك سيتغير أم لا. أعتقد أن المشكلة هي التوافق مع الإصدارات السابقة. من المحتمل أنه كان يجب أن يقرر قبل خروج 4.x.

نعم ، لن يتغير هذا السلوك في المستقبل القريب. لقد أعدت فتح هذه المشكلة ، لذلك عرفت أن أحقق فيها عندما سنحت لي الفرصة ، لأنني أتأكد من فهم ما يحدث مع كل تعليق يأتي إلى github النمس وكان هذا تعليقًا لم يكن لدي إجابة جيدة من أعلى رأسي. بالنظر عن كثب ، لا يمكننا تغيير هذا في المستقبل القريب بسبب semver ، ولكن هناك شيء للتحقيق فيما إذا كان يمثل نقطة ألم لكثير من المستخدمين.

لقد استخدمت هذا الحل مع تطور لأنك في وقت ما تريد كتابة مصفوفة فارغة وأحيانًا لا.

لذلك يبدو مقدس الخاص بي كما يلي:

        var schema = mongoose.Schema({
                   ...
           "children": [ String ]
                   ...
            });
        // turn off the saving of empty children if there are no children in the schema.
        schema.pre('save', function (next) {
            if (this.isNew) {
                if (this.children.length == 0) {
                    this.children = undefined;       
                }
                else if (this.children.length == 1 && this.children[0] == null) {
                    this.children = [];
                }                                                                                                                    
            }
            next();
        });
        var model = mongoose.model('MyDocument', schema);

ثم لأكتب أطفال فارغين أستخدم هذا:

idea.children = [null];

حيث يتم تجريد هذا:

idea.children = [];

قد لا يعمل هذا من أجلك ولكن يجب أن تكون قادرًا على التوصل إلى نوع آخر من المخططات.

هذه مشكلة كبيرة جدًا عندما يكون لديك مصفوفات داخل كائنات متداخلة.

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');

var quxSchema = new mongoose.Schema({ qux: String });
var fooSchema = new mongoose.Schema({ foo: { bar: { baz: [ quxSchema ] } } });
var Foo = mongoose.model('Foo', fooSchema);

var foo = new Foo({foo: undefined})
foo.save(function(err, foo) {
  console.log(JSON.stringify(foo)); // {"__v":0,"_id":"557ae56480f047fd4ff4ab26","foo":{"bar":{"baz":[]}}}
  Foo.find({ _id: foo._id }, function(err, foos) {
    console.log(JSON.stringify(foos[0])); // {"_id":"557ae56480f047fd4ff4ab26","__v":0,"foo":{"bar":{"baz":[]}}}
  });
});

أتوقع هنا أن يكون foo مفقودًا ، وبدلاً من ذلك لدي هذا الكائن المتداخل بمصفوفة فارغة.

ولكن لا يمكن أن يساعدك الحفظ المسبق هنا؟ بدلاً من استخدام {foo: undefined} ، يمكنك استخدام نوع فريد من foo للدلالة على null foo ، ثم إزالة foo في Presave.

على الرغم من القبيح.

لقد واجهت للتو نفس المشكلة مثل @ فايكينغ فعل. هل وجدت أي حل بديل مفيد؟

لقد جربتها بطريقة الحفظ "المسبقة" .. لكنها لا تزال تحدث في بعض الأحيان ، لست متأكدًا من عدد حالات الاستخدام المختلفة التي يتعين علي تغطيتها لإنجاز ذلك. أكبر مشكلتي في هذا هو أن JSON يجب أن تقدم كائنًا بالفعل ، وليس مصفوفة. هذا استثناء فادح لمحلل json الخاص بي الذي يحاول تعيين هذه الأشياء إلى كائنات جافا.

مثال:

var subA = mongoose.Schema({
     name: String,
     a: String
});

var subB = mongoose.Schema({
     name: String,
     b: String
});

var A = mongoose.Schema({
name: String,
filter: {
        lastupdate  : { type: Date, default: Date.now },
        subA: [{type: Schema.Types.ObjectId, ref: 'subA', unique: true}],
        subB: [{type: Schema.Types.ObjectId, ref: 'subB', unique: true}]
    }
});

var ModelA = mongoose.model('A', A);

var obj = new modelA();
obj.save();

... ينتج عن هذا:

{
 filter: []
}

ولكن يجب ألا يكون موجودًا ، أو على الأقل أن يكون كائنًا وليس مصفوفة فارغة:

{
 filter: {} 
}

أي شخص أي أفكار عن كيفية حل هذا؟

مع تحياتي

أعتقد أنه يمكنك جعل هذا العمل ، من الواضح أنه ليس مع العرض المسبق الذي نشرته ، لأن ذلك ينطوي على كون الأطفال مصفوفة وليس كائنًا. لم أجرب هذا ، لكن ألن يكون من الممكن استخدام كائن فارغ "كتابة بطة" للإشارة إلى كائن فارغ فعلي؟

لذلك قد يكون مقدمك:

if (this.isNew) {
    if (typeof(this.filter.empty) != "undefined") {
        this.filter = {};
    }
}

ثم لعمل مرشح فارغ فعلي ، يمكنك استخدام:

var obj = new modelA();
obj.filter = { empty: true };
obj.save();

لاحظ أنه لا يهم في الواقع إذا كان المخطط لا يحتوي على "فارغ" فيه ، فإنه لا يجعله نمسًا أبدًا.

بطريقة ما تمكنت من التغلب على المشكلة .. لقد فعلت شيئًا مشابهًا جدًا. رأيت إجابتك للتو وأردت أن أقول شكرًا لك :)

مع تحياتي
سيمون

كنت أواجه الكثير من المشاكل مع هذا الحل عندما كانت هناك مخططات متداخلة مع حقول اختيارية Array . لقد قمت بحل هذا من خلال إنشاء نوع جديد:

optional_array = 
  type: Mixed
  validate: 
    validator: (v) ->
      return v instanceof Array
    message: '{VALUE} needs to be an array.'

ثم قم بتعيين جميع الحقول على optional_array بدلاً من Array .

simllll أستخدم العنصر النائب null للكائنات المفقودة ثم أزل null قبل استخدام الكائن.

آسف ، لكن هذا تصميم مروع. لا يجب أن تقرر بالنيابة عني ما إذا كنت أريد أن يكون مصفوفة فارغة أو لا أضعها على الإطلاق. على الأقل توفير خيار لتعطيل هذه الميزة.

أتفق مع ifeltsweet

بعد أشهر ، هل هناك حل مناسب بدون ربط مسبق؟ لدي العشرات من حقول المصفوفات ، يجب أن أتعامل مع واحدًا تلو الآخر في خطاف مسبق ...

antonioaltamura لقد نسيت هذه المسألة ، أدناه يعمل في النمس 4.6:

const CollectionSchema = new Schema({
 field1: { type: [String], default: void 0 }, // <-- override the array default to be undefined
});

const Collection = mongoose.model('test', CollectionSchema);

Collection.create({}).
  then(doc => { console.log(doc); return doc; }).
  then(() => { process.exit(0); });

@ vkarpov15 الإصلاح الخاص بك لا يعمل بالنسبة لي على النمس 4.7.0. ما زلت تعمل بشكل جيد بالنسبة لك؟ لا يتضمن القيمة في إنشاء كائن جديد ولكن عندما أقوم بعمل Model.save ، فإنه يحاول إضافته مرة أخرى.

@ cpup22 هل يمكنك تقديم نموذج رمز؟ البرنامج النصي المشار إليه يعمل بشكل جيد بالنسبة لي في 4.7.1.

أعتقد أن الحل البديل من https://github.com/Automattic/mongoose/issues/2363#issuecomment -171988413 أكثر نظافة. يسمح بالتعيين الافتراضي إلى null حتى عند فشل default: null :

const CollectionSchema = new Schema({
  field1: { type: [String] },
});
CollectionSchema.methods.postconstructed = function () {
  this.field1 = null;
};
CollectionSchema.queue('postconstructed');

const Collection = mongoose.model('test', CollectionSchema);

Collection.create({}).then(doc => { console.log(doc); process.exit(0) });

بغض النظر ، لا يعمل عند تمرير قيمة (على سبيل المثال ، new Collection({ field1: [] }) يحصل على field1 === null . فقط إذا كان هناك خطاف بناء حدث قبل تطبيق البيانات التي تم تمريرها وبعد الافتراضي تم إنشاء مصفوفة فارغة. أو تم إصلاح هذا الخطأ للسماح default: null للمصفوفات.

أوه ، يبدو أن هذا يعمل:

const CollectionSchema = new Schema({
  field1: { type: [String], default: () => null },
});

يعمل شيء نوع المصفوفة الذي يحترمه بشكل أكثر صدقًا من القيم. لا توجد مشكلة في الكتابة فوق قيمة مصفوفة تم تمريرها null أو [] أو قيمة مصفوفة غير فارغة عبر Collection.create() أو new Collection() .

@ vkarpov15 مرحبًا ، لذلك حتى إذا لمصفوفة النوع إلى قيمة خالية في مخطط النمس الخاص بي قبل أن يحفظ mongo db مستندًا ، وعندما تكون المصفوفة فارغة ، يتم حفظها كمفتاح = فارغ.
لديك أي حلول

vikramkalta ، يرجى تقديم عينات من التعليمات البرمجية ، تحويلات تحويل النص إلى رمز عرضة للخطأ.

مرحبًا ، أنا أستخدم النمس 4.6.5 وما زلت أحفظ مصفوفة فارغة بهذه الحلول.

services: [{ type: Schema.Types.ObjectId, ref: 'Service', default: () => null }],

services: [{ type: Schema.Types.ObjectId, ref: 'Service', default: void 0 }],

@ keyboard99 يرجى اتباع التعليمات الموجودة في https://github.com/Automattic/mongoose/issues/1335#issuecomment -252129243. تعيّن الكود قيمة افتراضية لعناصر المصفوفة الفردية ، وليس للمصفوفة نفسها

هناك حل بسيط لهذه القضايا. ما عليك سوى تقديم القيمة الافتراضية على أنها غير محددة. على النحو التالي:

var BarSchema = new Schema({
    foos: {
        type: [FooSchema],
        default: undefined
    }
});

يعمل لدي

لكن هذا سيؤدي إلى تعقيدات مع array.push
:(

GeneralG هل هناك أي تعقيدات بخلاف التعقيدات الواضحة المتمثلة في الاضطرار إلى القيام بـ doc.array = doc.array || []; قبل استدعاء push() ؟

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات