Рубрики
Без рубрики

Как создавать отношения с мангустом и узлом. Js.

Фокус: однозначные отношения NoSQL базы данных, в отличие от баз данных SQL, как PostgreSQL, … Tagged Mongodb, Node, JavaScript, база данных.

Фокус: Отношения из одной ко многим

NoSQL базы данных, в отличие от баз данных SQL, такими как postgresql, mysql и т. Д., которые традиционно построены для управления отношениями на данных, проиндексированные и ссылки на несколько таблиц, имеют плохую или почти несуществующую поддержку для отношений в ее съемочной схеме. MongoDB, популярная база данных NoSQL, как и другие, имеют встроенные методы, которые разработчики могут использовать отношения для создания отношений между несколькими схемами.

Отношения в MongoDB построены на функциональности соединения и с популярным модулем NPM, библиотекой Mongoose, разработчики могут использовать свою необработанную мощность, создавать сложные отношения и главное, разработать эффективные базы данных, чтобы избежать дроссельных запросов, как это было бы сделано, если бы Работа с базой данных SQL.

В этом руководстве я собираюсь прикоснуться к следующим образом:

  • Типы отношений и ссылочных типов объектов в MongoDB
  • Mongoose Насел метод
  • Виртуальные мангусты

Предпосылки:

Ожидается, что у читателей есть хорошая базовая хватания Expressjs, Mongoose, ES6 + JS & Postman.

Кроме того, следующее должно быть доступно либо в качестве сервиса, либо установлена и работает на месте на вашем компьютере:

  • Монгодб или вы можете выбрать Atlas, облачную версию MongoDB.
  • Mongoose NPM. Просто запустите [NPM I Mongoose] в корне папки проекта.
  • Почтальон, чтобы проверить конечные точки.
"npm i mongoose"

С целью этой записи я построил маленький «Издательство» Проект, чтобы пройти вас через то, как добиться любого из методов для обсуждения. Проект издательства предполагает, что издатели как зарегистрированные пользователи, которые могут публиковать несколько книг под их портфолио.

  • MongoDB в качестве базы данных.
  • Библиотека Mongoose, как диспетчер документов объекта базы данных (ODM).
  • Expressjs для создания наших маршрутов с помощью Async/await ES6 +, поскольку мы будем иметь дело с обещаниями.
  • Почтальон будет использоваться для проверки наших конечных точек для ответов.

Мангуст Представляет реляционные данные с использованием двух основных моделей дизайна, а также выбор модели для развертывания при планировании коллекций базы данных любого проекта, преимущественно навес на размер данных, точность данных и частоту доступа. Тем не менее, правило большого пальца, размер хранения документов находится в непосредственной близости от скорости, при которой запросы разрешаются, и, в конечном итоге, насколько исполняется базу данных.

Две модели следующие:

  1. Встроенные модели данных [денормализация]: Это наименее рекомендуемая форма отношений. Данные просто денормалируются путем встраивания детей (связанные) документы прямо в родительский (основной) документ. Используя наш «Проект публикации» в качестве примера, это означало бы, что издатели хранят все опубликованные книги и связанную с ними непосредственно на объекте каждого издателя. В типичном однозначном документе это будет работать отлично, поскольку ожидаемый размер документов не более 20. Однако При работе с дочерними документами более широкого размера этот размер тяжело ухудшает производительность базы данных, вызывая отставание и трудности в сохранении синхронизации данных, в конечном итоге, приносящий плохой пользовательский опыт.

  2. Ссылаженная модель данных [Нормализация]: Когда данные нормализуются, это означает, что документы разделены на разные коллекции, и они обмениваются ссылками между собой. В большинстве случаев одно обновление в родительском документе со всеми параметрами прошло, обновляет дочерние документы непосредственно на него. Остальная часть этого урока будет сосредоточена на максимальном применении этого метода, и как наилучшим образом организовать наши коллекции базы данных и документы.

Ссылки на документы между коллекциями могут быть выполнены с помощью двойных подходов, и следующие:

  • Рекомендация ребенка: Документ считается упомянутым ребенком, когда родительский документ хранит ссылку на свои детские коллекции, сохраняя свои идентификаторы – в большинстве ситуаций, идентификатора, в массиве аналогичных идентификаторов на родительском документе. Ссылаясь на проект нашего «издательства», это означало бы, имея издатели хранить книгу ._ID для каждой созданной книги, в массиве идентификатора книги, предопределенных на схеме издателя, а также при необходимости привлечь эти дочерние документы с использованием метода заполнения.

Из нашего проекта см. Схему издателя ниже:

const mongoose = require('mongoose');
const {Schema} = require('mongoose');

const publisherSchema = new Schema({
   name: String,
   location: String,
   publishedBooks: [{
      type: Schema.Types.ObjectId,
      ref: 'Book'
   }]
},
{timestamps: true});

module.exports = mongoose.model('Publisher', publisherSchema);

Вот наша книжная схема:

const mongoose= require('mongoose');
const {Schema} = require('mongoose');

const bookSchema = new Schema({
   name: String,
   publishYear: Number,
   author: String,
   publisher: {
      type: Schema.Types.ObjectId,
      ref: 'Publisher',
      required: true
   }
},
{timestamps: true});

module.exports = mongoose.model('Book', bookSchema);

Схема книги

Метод Mongoose «заполнил» нагружает детали каждого ссылочных дочерних документов и возвращает его рядом с документом каждого издателя, выявленного из БД. Давайте посмотрим пример этого, используя наш проект.

Начнем с создания нового издателя ниже:

/***
 * @action ADD A NEW PUBLISHER
 * @route http://localhost:3000/addPublisher
 * @method POST
*/
app.post('/addPublisher', async (req, res) => {
   try {
      //validate req.body data before saving
      const publisher = new Publisher(req.body);
      await publisher.save();
      res.status(201).json({success:true, data: publisher });

   } catch (err) {
      res.status(400).json({success: false, message:err.message});
   }
});
{
    "success": true,
    "data": {
        "publishedBooks": [],
        "_id": "5f5f8ac71edcc2122cb341c7",
        "name": "Embedded Publishers",
        "location": "Lagos, Nigeria",
        "createdAt": "2020-09-14T15:22:47.183Z",
        "updatedAt": "2020-09-14T15:22:47.183Z",
        "__v": 0
    }
}

Далее недавно созданный издатель продолжается добавить новую книгу о публикации в БД. Издатель _ID передается как значение для ключа издателя в схеме книги перед сохранением, и в том же контуре запроса, сразу после вызова метода сохранения в новой книге, вновь созданный объект книги, возвращаемый из обещания, должен быть прошедший в качестве параметра к методу push, вызываемый на ключ издателя. Это гарантирует, что объект книги сохранен на документе издателя.

Вот волшебная поломка:

/***
 * @action ADD A NEW BOOK
 * @route http://localhost:3000/addBook
 * @method POST
*/

app.post('/addBook', async (req, res)=>{

   /**
    * @tutorial: steps
    * 1. Authenticate publisher and get user _id.
    * 2. Assign user id from signed in publisher to publisher key.
    * 3. Call save method on Book.
   */

   try {
      //validate data as required

      const book = new Book(req.body);
      // book.publisher = publisher._id; <=== Assign user id from signed in publisher to publisher key
      await book.save();

      /**
       * @tutorial: steps
       * 1. Find the publishing house by Publisher ID.
       * 2. Call Push method on publishedBook key of Publisher.
       * 3. Pass newly created book as value.
       * 4. Call save method.
      */
      const publisher = await Publisher.findById({_id: book.publisher})
      publisher.publishedBooks.push(book);
      await publisher.save();

      //return new book object, after saving it to Publisher
      res.status(200).json({success:true, data: book })

   } catch (err) {
      res.status(400).json({success: false, message:err.message})
   }
})

Это определенный способ сохранения ссылок на дочерние документы (ID) в документе издателя. При успешном создании ниже возвращается, когда вы запрашиваете I Publisher I d.

PS: Издатель ниже создал 3 новых книги.

{
    "publishedBooks": [
        {
            "_id": "5f5f8ced4021061030b0ab68",
            "name": "Learn to Populate virtuals Mongoose",
            "publishYear": 2019,
            "author": "Devangelist"
        },
        {
            "_id": "5f5f8d144021061030b0ab6a",
            "name": "Why GoLang gaining traction",
            "publishYear": 2020,
            "author": "John Doe"
        },
        {
            "_id": "5f5f8d3c4021061030b0ab6b",
            "name": "Developer Impostor syndrome",
            "publishYear": 2021,
            "author": "John Mark"
        }
    ],
    "_id": "5f5f8ac71edcc2122cb341c7",
    "name": "Embedded Publishers",
    "location": "Lagos, Nigeria",
    "createdAt": "2020-09-14T15:22:47.183Z",
    "updatedAt": "2020-09-14T15:33:16.449Z",
    "__v": 3
}

Тем не менее, если метод Push и Save не вызывается в документе издателя, издателем, хотя существуют, а новая созданная книга, вернет пустой массив опубликованных книг, как видно ниже, когда запрашивается.

{
    "success": true,
    "data": {
        "publishedBooks": [],
        "_id": "5f5f8ac71edcc2122cb341c7",
        "name": "Embedded Publishers",
        "location": "Lagos, Nigeria",
        "createdAt": "2020-09-14T15:22:47.183Z",
        "updatedAt": "2020-09-14T15:22:47.183Z",
        "__v": 0
    }
}

Несмотря на успех метода ссылки на ребенка, его ограничение, как показано выше, состоит в том, что размер массива идентификатора может стать очень большим быстро, что, следовательно, видение базы данных теряет эффективность и производительность сверхурочно, поскольку размер массива растет. MongoDB официально распознает это как анти-шаблон, и решительно препятствует его использованию Для документооборочных отношений работает в масштабе.

  • Родитель ссылки: С другой стороны, ориентирован на родитель, с другой – TAD отличается от обращения к ребенку, как описано ранее, в том, что только дочерние документы хранят ссылку на родительские документы. Эта ссылка по отдельности сохраняется на каждом дочернем документе, созданном, определенном как идентификатор объекта на схеме. Набор родительских документов, наоборот, не поддерживают прямую ссылку, но строит одну с помощью метода мангея, называемых виртуальными.

Мангуст виртуальный Является гораздо более сложным подходом к получению ссылок на дочерние документы, и оно главное, занимает меньше памяти для хранения данных, поскольку новый виртуальный мангуст для полей ключей создает всякий раз, когда запрос работает, не сохраняется на родительском документе. Изредка виртуальные виртуальные также называют «обратным заполнением», как таковые, когда вы слышите, как люди упоминают, что, не лада!

Достаточно с разговором, давайте прыгнем в наш код проекта. Во-первых, давайте посмотрим, что похоже на наша книжная схема:

const mongoose= require('mongoose');
const {Schema} = require('mongoose');

const bookSchema = new Schema({
   name: String,
   publishYear: Number,
   author: String,
   publisher: {
      type: Schema.Types.ObjectId,
      ref: 'Publisher',
      required: true
   }
},
{timestamps: true})

module.exports = mongoose.model('Book', bookSchema);

Далее, где ложь сложная часть, является нашим родительским документом. Обратите внимание на то, как определены виртуальные виртуалы, и важная часть этого является дополнительными параметрами, которые мы должны установить на схеме, без которых никакие результаты не возвращаются. Эти дополнительные варианты являются Тоджсон и Тообъектировать опции. Они оба по умолчанию для false, и являются ядром для обеспечения того, чтобы всякий раз, когда родительский документ запрашивается, когда эти параметры настроены на True, результаты передаются на метод .json () в связи с ответом.

const mongoose = require('mongoose');
const {Schema} = require('mongoose');

const publisherSchema = new Schema({
   name: String,
   location: String
},
   {timestamps: true}
);

/**
 * @action Defined Schema Virtual
 * @keys 
 *    1.   The first parameter can be named anything.
 *          It defines the name of the key to be named on the Schema
 * 
 *    2. Options Object
 *       ref: Model name for Child collection
 *       localField: Key for reference id, stored on Child Doc, as named on Parent Doc.
 *       foreignField: Key name that holds localField value on Child Document
 */
publisherSchema.virtual('booksPublished', {
   ref: 'Book', //The Model to use
   localField: '_id', //Find in Model, where localField 
   foreignField: 'publisher', // is equal to foreignField
});

// Set Object and Json property to true. Default is set to false
publisherSchema.set('toObject', { virtuals: true });
publisherSchema.set('toJSON', { virtuals: true });


module.exports = mongoose.model('Publisher', publisherSchema);

Определение виртуального объекта наступает следующий, и лучший способ легко запомнить, как его определить ( намного проще, если вы с фона SQL ), является;

Выберите «Имя для виртуального поля» от « Ref – Имя коллекции ребенка “, где” местное поле – родительский ключ, хранящийся на сборе детей, в основном ID “равен” _foreignfield – имя ключа ребенка схемы, хранение родительского идентификатора, как его значение.

При определении обоих вариантов, когда мы заполним наш издатель после вызова метода Get, нам гарантированно извлечь все книги, опубликованные каждым издателем, и для дальнейшей специфики, поскольку не вся информация о книге будет необходима, выберите необходимые ключи из каждой книги и верните ее в тело в ответ.

Посмотрите, как это делается в нашем проекте ниже:

/***
 * @action GET ALL PUBLISHERS
 * @route http://localhost:3000/publishers
 * @method GET
 */
app.get('/publishers', async (req, res) => {
   try {
      const data = await Publisher.find()
                                 .populate({path: 'booksPublished', select: 'name publishYear author'});
      res.status(200).json({success: true, data});
   } catch (err) {
      res.status(400).json({success: false, message:err.message});
   }
})
{
    "success": true,
    "data": [
        {
            "_id": "5f5f546e190dff51041db304",
            "name": "Random Publishers",
            "location": "Kigali, Rwanda",
            "createdAt": "2020-09-14T11:30:54.768Z",
            "updatedAt": "2020-09-14T11:30:54.768Z",
            "__v": 0,
            "booksPublished": [
                {
                    "_id": "5f5f548e190dff51041db305",
                    "name": "Mastering Mongoose with Javascript",
                    "publishYear": 2020,
                    "author": "Devangelist",
                    "publisher": "5f5f546e190dff51041db304"
                },
                {
                    "_id": "5f5f55ca190dff51041db307",
                    "name": "Learning Mongoose Populate method",
                    "publishYear": 2019,
                    "author": "Devangelist",
                    "publisher": "5f5f546e190dff51041db304"
                }
            ],
            "id": "5f5f546e190dff51041db304"
        }
}

Сумма, родительская ссылка – лучший подход к ссылке при использовании нормированного метода модели и справиться с большим набором данных.

Если вы доверяли это до этого момента, спасибо за чтение, и я надеюсь, что вы узнали что-то – [Новое]. Я рад больше пообщаться о новых знаниях, возможностях и возможных исправлениях. Я могу добраться в Twitter Via, @oluseyeo_ или по электронной почте AT, sodevangeList@gmail.com. .

Счастливый взлом 💥 💥

TL: DR;

  1. Существует два подхода моделирования, встроенные и ссылки.
  2. Встраивается только тогда, когда ваши данные будут доступны реже, и вы в основном только читаете данные.
  3. Для более крупных IOPS используйте модель ссылки.
  4. Ссылка может быть сделана двумя способами, редкой и родительской ссылкой.
  5. Если размер дочернего документа небольшой, до 100, используйте привязку к ребенку. Это хранит клавишу Child Reference непосредственно на родительском документе, используя метод push.
  6. Если размер дочерних документов является огромным, используйте опцию «Назначение родительских ссылок», обратное заполнение родительских документов с использованием Virtual Mongoose.

Рекомендуется дальше чтения: Шаблоны доступа к данным Монгусная документация Денормализация

Оригинал: “https://dev.to/oluseyeo/how-to-create-relationships-with-mongoose-and-node-js-11c8”