Mongoose: تحويل كافة ObjectIds إلى سلسلة باستخدام أسلوب Document.toObject ()؟

تم إنشاؤها على ٢٥ مارس ٢٠١٥  ·  24تعليقات  ·  مصدر: Automattic/mongoose

كما اكتشفت أن _id في المستند لا يزال يمثل ObjectId بعد toObject ()

هل هناك طريقة لتحقيق ذلك؟

help

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

هذه الميزة في Mongo مؤسفة حقًا

ال 24 كومينتر

لدي نفس الخطأ. لا يقوم كلا من toJSON() و toObject() بترتيب مثيلات ObjectId .

هذا حسب التصميم الآن ، لأن ObjectIds تقنيًا ليست سلاسل. بعيدًا عن رأسي ، فإن الطريقة الوحيدة التي يمكنني التفكير بها هي JSON.parse(JSON.stringify(doc)); ما هي حالة الاستخدام الخاصة بك لتجميد جميع معرفات الكائنات؟

إذن ، الوظيفة toJSON() لا تقوم بتحويل الكائن إلى سلسلة JSON؟ ليس _id والتاريخ سلسلة بل كائن؟

بالمناسبة ، ما الفرق بين toObject() و toJSON() ؟
شكرا!

يجب أن يظل التاريخ نعم تاريخًا ، وليس سلسلة ، بعد toJSON() + toObject() .

toJSON() و toObject() متطابقان بشكل أساسي ، والفرق الوحيد هو أنه عندما تفعل JSON.stringify(doc) تبحث JavaScript عن وظيفة toJSON() في المستند وتستخدمها لتحويل هدف. لذا فإن سبب toJSON() هو السكر النحوي لـ JSON.stringify() .

@ vkarpov15 آسف للتعليق على موضوع مغلق ، لكنه يبدو المكان الأكثر صلة بالنشر ، لأنه مرتبط مباشرة بهذه المشكلة.

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

الطريقة الوحيدة التي تمكنت من القيام بها حتى الآن هي القيام بذلك:

var objectdiff = require('object-deep-diff');

var diffresult = objectdiff(
  JSON.parse(JSON.stringify(doc1.toObject())),
  JSON.parse(JSON.stringify(doc2.toObject()))
);

يبدو أن هذه طريقة مكلفة للحصول على فرق بين الأشياء.
هل تعرف طريقة أفضل لمقارنة مستندات النمس بشكل موثوق؟

لست متأكدًا من كيفية عمل الاختلافات العميقة ولكنها قد تواجه بعض المشكلات مع mongodb ObjectIds. حاول تحويل _id وحقول الكائن الأخرى إلى سلاسل. أو فقط استخدم فحص لوداش العميق للمساواة ، أعتقد أن المرء يعمل مع ObjectIds

يستخدم فرق عميق @ vkarpov15 لوداش لفحص المساواة ، لذلك للأسف لن ينجح ذلك:
https://github.com/rbs392/object-deep-diff/blob/master/index.js

سيعمل تحويل جميع معرفات الكائن إلى سلاسل ، ولكن نظرًا لأن الكائنات يمكن أن تحتوي على مصفوفات و / أو كائنات أخرى متداخلة ، فإن ذلك يصبح مهمة مكلفة جدًا للقيام بها أيضًا ..: /

إذن ، هذا سؤال آخر ، هل تستخدم فرقًا عميقًا على وثيقتين من النمس أم مستندين ناتج عن toObject() ؟ هذا الأخير يجب أن يعمل ، السابق ليس كثيرًا.

@ vkarpov15 يكون عادةً مستندًا نمسًا واحدًا (تم تحويله إلى كائن جافا سكريبت به كائن .toObject) وكائن جافا سكريبت عادي.
السبب هو أنني بحاجة إلى مقارنة البيانات الواردة من العميل مع البيانات الموجودة بالفعل في قاعدة البيانات.
لذلك ، فإن البيانات الواردة من العميل قد تم تحويلها بالفعل إلى ObjectID ، لكن البيانات القادمة من قاعدة البيانات لم يتم تحويلها.
ولكن نظرًا لأنني أقوم بإجراء هذا الفحص العميق في مكون إضافي من mongoose ، فأنا بحاجة إلى التأكد تمامًا من أن كلا المستندين تم إنشاؤهما بشكل متماثل ، ولهذا السبب يتعين علي تشغيل JSON.parse (JSON.stringify (doc.toObject ()) ) في كلا المستندين.

نعم في هذه الحالة ، ستحتاج إلى إجراء JSON.parse(JSON.stringify()) ، فهذه أسهل طريقة لتحويل جميع معرفات الكائن إلى سلاسل.

كان JSON.parse(JSON.stringify()) مكثفًا جدًا من الناحية الحسابية بالنسبة لي ، لذلك كان عليّ إنشاء هذا lib التفكير المثالي .

var transformProps = require('transform-props');

function castToString(arg) {
    return String(arg);
}

var doc = new MongooseModel({ subDoc: { foo: 'bar' }});
var docObj = doc.toObject();

transformProps(docObj, castToString, '_id');

console.log(typeof docObj._id); // 'string'
console.log(typeof docObj.subDoc._id); // 'string'

هذه الميزة في Mongo مؤسفة حقًا

ZacharyRSmith إذن ماذا عن الدعائم الأخرى ، على سبيل المثال. author_id (معرّف الكائن يشير إلى نموذج المستخدم) / author_ids (مصفوفة ObjectIds)؟

@ flight9 يمكنك إخبار convertProps () للبحث عن مفاتيح متعددة. شاهد هذا الاختبار هنا: https://github.com/ZacharyRSmith/transform-props/blob/master/index.test.js#L67

أعتقد أنه يمكنك الحصول على ما تريد من خلال هذا:

function myToString(val) {
  if (Array.isArray(val)) {
    return val.map(item => String(item));
  }
  return String(val);
}

transformProps(obj, myToString, ['author_id', 'author_ids']);

ZacharyRSmith شكرًا على الحل ، إنه رائع!

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

const ObjectID = require('mongodb').ObjectID;

/**
 * Convert ObjectId field values inside an object to String type values
 * (includes array of ObjectIds and nested ObjectId fields)
 * <strong i="9">@param</strong> obj Object - The Object to be converted.
 * <strong i="10">@return</strong> none
 */
function objectIdtoString(obj) {
  for(let k in obj) {
    let v = obj[k];
    if(typeof v == 'object') {
      if(k.endsWith('_id') && v instanceof ObjectID) {
        obj[k] = v.toString();
      }
      else if(
        k.endsWith('_ids') && Array.isArray(v) &&
        v.length > 0 && v[0] instanceof ObjectID
      ) {
        let vs = [];
        for(let iv of v) {
          vs.push(iv.toString());
        }
        obj[k] = vs;
      }
      else {
        objectIdtoString(v);
      }
    }
  }
}

// Call example
objectIdtoString(obj):

هههههههههههههه

نعم في هذه الحالة ، ستحتاج إلى إجراء JSON.parse (JSON.stringify ()) ، هذه هي أسهل طريقة لتحويل جميع معرفات الكائن إلى سلاسل.

https://medium.com/ft-product-technology/this-one-line-of-javascript-made-ft-com-10-times-slower-5afb02bfd93f

TLDR. JSON.parse(JSON.stringify()) مهمة متزامنة محظورة ويمكن أن تسبب اختناقات خطيرة. لا ينبغي أن يكون هذا هو الحل المقبول / المقترح لهذه المشكلة ...

يجب أن تكون أيضًا قادرًا على القيام بـ mongoose.Types.ObjectId.prototype.toJSON = function() { return this.toString(); . ولكن حتى هذه المقالة تقول ، JSON.parse (JSON.stringify) هي واحدة من أسرع الطرق للقيام بالاستنساخ العميق ، كانت مشكلتهم أنهم كانوا استنساخًا عميقًا بشكل متكرر وغير ضروري

إذن ، ها هو 2019.
هل لدينا حتى الآن طريقة لطيفة ونظيفة وواضحة للحصول على سلسلة سداسية عشرية من كل مثيل ObjectId على الكائن؟

تضمين التغريدة

mongoose.ObjectId.get(v => v.toString());

انظر: http://thecodebarbarian.com/whats-new-in-mongoose-54-global-schematype-configuration.html#schematype -getters

@ vkarpov15 يبدو أن هذا ليس حلاً عند استخدام "lean".
لذا ، إذا كانت النتيجة المرجوة هي إرجاع كائن json عادي مع سلسلة objectIds ، يبدو أن الطريقة الأكثر فعالية لتحقيق ذلك هي الاستمرار في استخدام JSON.parse(JSON.stringify()) مع الخيار lean .

أو ربما مكونًا إضافيًا بسيطًا: https://www.npmjs.com/package/mongoose-lean-objectid-string

nhitchins صحيح ، يجب عليك استخدام مكون إضافي مثل mongoose-lean-getters .

@ vkarpov15 هذا من المفترض أيضًا أن يعمل مع مخطط مميز؟ لدي مخطط أساسي يمكنني من خلاله إنشاء متغيرات. حاولت وضع حاصل على المخطط الأساسي. أنا أستخدم lean () واستخدمت mongoose-lean-getters لكنني لم أتمكن من تشغيل هذا.

pwrnrd ، هل يمكنك من فضلك فتح إصدار جديد واتباع نموذج الإصدار؟ يجب أن تعمل بشكل جيد مع مخطط مميز.

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