Mongoose populate ви позволява да замените указаните пътища в документа с документ(и) от друга колекция(и). Той е добре известен и добре документиран. Ако не сте запознати с него, препоръчвам ви да прочетете следното, преди да продължите https://mongoosejs.com/docs/populate.html.

Когато търсите този метод, повечето уроци го използват като примера, даден в официалната документация. От моя опит това е грешка. Документацията е тук, за да покаже как работи методът, а не да даде насоки за архитектурата. Трябва да го видите като инструмент, който да използвате при избора на архитектура на вашата база данни.

Независимо дали сте back-end или full-stack разработчик, трябва да помислите за интеграцията с front-end кода. Ако използвате mongoose, шансовете са, че работите с JS стек.

Днес повечето от предните рамки на JS са добре структурирани и позволяват писане. Данните, които вашият API изпраща обратно, трябва да са ясни, така че:

  • новите разработчици не трябва да гадаят какво съдържат.
  • разработчиците от предния край могат да дефинират въведени модели.

Начинът, по който mongoose populate се използва през повечето време, води до непоследователно въвеждане и повишена сложност, която може да бъде избегната.

В документацията можете да видите пример с модели Story и Person. Това е добър пример за показване как работи попълването. Според мен не е добре да показваш как трябва да го използваш. Нека го разгледаме заедно.

За нашия пример ще го опростим:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const personSchema = Schema({
    _id: Schema.Types.ObjectId,
    name: String,
    age: Number,
});
const storySchema = Schema({
    author: { type: Schema.Types.ObjectId, ref: 'Person' },
    title: String,
});
const Story = mongoose.model('Story', storySchema);
const Person = mongoose.model('Person', personSchema);

Ако направите това, Story.findOne() ще върне нещо като:

{
    _id: 'some-id',
    author: 'some-other-id',
    title: 'some-title'
}

докато Story.findOne().populate('author') ще върне нещо като:

{
    _id: 'some-id',
    author: { _id: 'some-other-id', name: 'some-name', age: 21 },
    title: 'some-title'
}

Както можете да видите, полето „автор“ съхранява ObjectId. Когато го попълните, той ще съдържа човек. Това не е последователно, така че искаме да избегнем това, особено ако планираме да изпратим тези данни през API.

Едно просто решение може да бъде винаги или никога да не попълвате полето. Това ще доведе до едно от двете

  • понякога се връщат безполезни данни
  • допълнителни искания, които биха могли да бъдат избегнати

Можете също така да въведете данните в предния код, за да бъдат или низ, или човек. Но това ще означава по-защитен код и повишена сложност.

Това може да е добре в началото. Но когато приложението ви се разраства и употребите се умножават, ще бъде по-трудно да го следите. Новите разработчици ще имат нужда от повече време, за да разберат кода. Това е важно, дори ако знаете, че сте сами в проекта. Когато не работите върху дадена функция за известно време, вие също ще имате нужда от повече време, за да си спомните как работи.

Това ще бъде проблем, особено при скорошната технология отпред, като Flutter, защото трябва да въведете всички данни.

Все още е добър за някои случаи на употреба, но през повечето време бих препоръчал да използвате mongoose virtuals за попълване на вашите взаимоотношения. Според моя опит дава по-опростен и чист код:

Използвайте полето за съхраняване на идентификатора и виртуално за зареждане на документа(ите).

Нека приложим това към нашия предишен пример:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const personSchema = Schema({
    _id: Schema.Types.ObjectId,
    name: String,
    age: Number,
});
const storySchema = Schema({
    author_id: { type: Schema.Types.ObjectId, ref: 'Person' },
    title: String,
});
storySchema.virtual('author', {
    justOne: true,
    localField: 'author_id',
    foreignField: '_id',
    ref: 'Person'
});
const Story = mongoose.model('Story', storySchema);
const Person = mongoose.model('Person', personSchema);

Във вашия преден код можете да въведете author_id като низ или ObjectId и author като Person.

По този начин кодът остава чист и последователен.

Освен това ще бъде по-гъвкав за бъдещи подобрения. Виртуалното попълване ви позволява да дефинирате по-сложни взаимоотношения, можете да добавите виртуални „истории“, „последна_история“ … към схемата Person, без промяна в базата данни, което означава без миграции.

Кажете ми какво мислите за тази статия!