Mongoose subdocument – Sự phụ vào parent document

Subdocument là một document được nhúng bên trong một document khác. Nghĩa là bạn có thể lồng bất cứ một schema này vào một schema khác.

Mongoose có 2 khái niệm về subdoccument: array subdocument và single nested.

// File mongoose.subdocument.js
var childSchema = new mongoose.Schema({ name: 'string' });

var parentSchema = new mongoose.Schema({
  // Array of subdocuments
  children: [childSchema],
  // Single nested subdocuments. Work với mongoose >= 4.2.0
  child: childSchema
});

Một subdocument hoàn toàn giống với document thông thường. Chúng cũng có các middleware, validation, virtuals etc. Một điểm khác biết lớn nhất là subdocument không được lưu riêng lẽ, chúng phải được lưu với document chứa nó(parent document).

// file mongoose.subdocument.js

var Parent = mongoose.model('Parent', parentSchema);
var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
parent.children[0].name = 'Matthew';

// `parent.children[0].save()`sẽ kích hoạt tricker middle 
parent.save(callback);

Subdocument hook

Như đã nói ở trên, subdocument cũng giống như một document bình thường. Nên chúng cũng sẽ có các hook trigger. Ví dụ như khi parent document save() thì hook trigger save() của subdocument cũng được gọi.

// File mongoose.subdocument.js
childSchema.pre('save', function (next) {
    if ('invalid' == this.name) {
        return next(new Error('#sadpanda'));
    }
    next();
});

var parent = new Parent({ children: [{ name: 'invalid' }] });
parent.save(function (err) {
    console.log(err.message) // #sadpanda
});
Run:
  • MacOS: ./node_modules/.bin/babel-node mongoose.document.js
  • Windows: .\node_modules\.bin\babel-node mongoose.document.js

Output: #sadpanda

Tìm kiếm subdocument trong document

Mặc định mỗi subdocument đều có _id. Mongoose document array( document có type array) có sẵn method id hỗ trợ tìm kiếm một subdocument theo _id.

var doc = parent.children.id(_id);

Thêm subdocument vào array

MongooseArray có các method như push, unshift, addToSet để thêm một subdocs vào array.

// File mongoose.subdocument.js
var Parent = mongoose.model('Parent');
var parent = new Parent;

// create a comment
parent.children.push({ name: 'Liesl' });
var subdoc = parent.children[0];
console.log(subdoc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
subdoc.isNew; // true

parent.save(function (err) {
  if (err) return handleError(err)
  console.log('Success!');
});
Run:
  • MacOS: ./node_modules/.bin/babel-node mongoose.document.js
  • Windows: .\node_modules\.bin\babel-node mongoose.document.js

Output: Success!

Xoá subdocumet

Mỗi subdocument đều có method remove() để xoá nó ra khởi array nếu nó là arraysubdoc, hoặc xoá nó ra khởi parent documet nếu single nested.

parent.children.id(_id).remove();
// Equivalent to `parent.child = null`
parent.child.remove();
parent.save(function (err) {
  if (err) return handleError(err);
  console.log('the subdocs were removed');
});

Get Parent docuement từ subdocumet

Gọi parent() để lấy parent của subdocument.

// File mongoose.subdocument.js
const getParentDoc = async () => {
    const doc = new Parent({
        children: [{ name: 'foo' }],
        child: { name: 'bar' }
      });
      console.log(doc)
      console.log(doc.child.parent() === doc); // true
      console.log(doc.children[0].parent() === doc); // true
}


getParentDoc();
Run:
  • MacOS: ./node_modules/.bin/babel-node mongoose.document.js
  • Windows: .\node_modules\.bin\babel-node mongoose.document.js

Output:

true
true

Nếu có nhiều subdocument lồng nhau, bạn có thể gọi ownerDocument() để lấy top-level document.

const schema = new Schema({
  level1: new Schema({
    level2: new Schema({
      test: String
    })
  })
});
const Model = mongoose.model('Test', schema);

const doc = new Model({ level1: { level2: 'test' } });

doc.level1.level2.parent() === doc; // false
doc.level1.level2.parent() === doc.level1; // true
doc.level1.level2.ownerDocument() === doc; // true

Kết

Them mình nghĩ subdocument khá giống với quan hệ (one – to – one, one – to – many) trong cơ sở dữ liệu quan hệ. Array subdocument tương ứng one – to – manysingle nestedone – to one.

Source code demo

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x