Связь «многие к одному» в MongoDB

#spring #mongodb #spring-data-mongodb

#spring #mongodb #spring-data-mongodb

Вопрос:

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

У меня типичная ситуация с отношением «многие к одному». Пожалуйста, не говорите мне, что MongoDB не является реляционной базой данных, потому что я это уже знаю. Ключевой момент — реальность работает определенным образом, и мне нужно, чтобы мое приложение отражало это. Реальный мир полон отношений, и если ваш ответ «выберите другую базу данных для вашего случая», то я думаю, что команда MongoDB могла бы закрыть свой бизнес, потому что их продукт был бы совершенно бесполезен в таком случае.

Итак, давайте предположим типичное отношение сотрудник / отдел. Сотрудник связан с одним отделом. В отделе может быть ноль или несколько сотрудников.

Давайте предположим, что очень простые модели:

 public class Department {

    private String name;

   // something like...
   private List<Employee> employees;

}

public class Employee {

    private String name;

   // something like...
   private Department department;

}
  

Теперь в моем REST API мне нужно несколько довольно простых функций:

  • получить список всех отделов
  • получите список всех сотрудников, но он должен содержать название отдела для каждого сотрудника
  • получить список сотрудников для выбранного отдела

Итак, как бы вы решили это с помощью MongoDB? Я также использую Spring Boot с данными Spring, но я думаю, что это не имеет большого значения.

Я сталкивался с разными подходами, но все они кажутся мне очень плохими. Встраивание отдела в сотрудника сделает невозможным получение списка всех отделов или сотрудников одного отдела. Встраивание сотрудников в отдел сделает невозможным получение списка всех сотрудников. Использование @DBRef будет имитировать связь, но тогда как мне получить список сотрудников, включая названия отделов, без вызова REST API для каждого сотрудника?

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

Спасибо

Комментарии:

1. «Действительно ли возможно, что MongoDB не может решить такую супер простую проблему?» — MongoDB предназначен для документов, а не для объектов с отношениями. Самым простым способом было бы иметь одну коллекцию с отделами для вашего варианта использования «получить список всех отделов» и одну коллекцию со всеми сотрудниками с их идентификатором отдела и / или именем для вашего второго и третьего варианта использования. Если вы больше заботитесь о согласованности, чем о времени выполнения, сотрудник может содержать только идентификатор отдела, но тогда вам нужно получить доступ к коллекции «отдел» для каждого сотрудника, чтобы загрузить название его отдела.

2. Я не думаю, что в реальном мире даже существует такая ситуация, когда у вас были бы сущности без каких-либо отношений между ними. Если MongoDB действительно построен на таком предположении, то OMG 🙂

3. Не могли бы вы уточнить «доступ к коллекции «отдел» для каждого сотрудника, чтобы загрузить название его отдела»? Я имею в виду — как мне реализовать это в Java Spring?

4. Отношения могут быть заменены избыточностью, это позиция MongoDB. Что касается вашего вопроса: я запросил MongoDB вручную, поэтому после загрузки всех сотрудников вам необходимо сопоставить документы MongoDB с вашей собственной моделью данных, где для создания Employee объекта вам необходимо загрузить соответствующий Department (отфильтрованный по идентификатору) из коллекции отделов. Я понятия не имею, что Spring Data может делать с MongoDB, хотя.

5. спасибо, в конце концов мне удалось это реализовать. Не очень доволен этим методом, но, по крайней мере, он работает.

Ответ №1:

Может быть, вы можете использовать простой departmentId (со значением идентификатора Mongo для отдела) в вашем документе сотрудника?

Таким образом, вы избегаете встроенного документа, и ваши варианты использования могут работать :

  1. Случай «Все отделы» — это просто поиск всего в коллекции отделов.
  2. All employees — это поиск всего в коллекции employees, а затем на вашем сервере вам нужно вызвать коллекцию department для всех отдельных идентификаторов отдела, которые существуют в employees.
  3. Все сотрудники для выбранного обращения в отдел — это идентификатор поиска по отделу в коллекции employees.

Будет ли это работать для вас приемлемым образом?

Комментарии:

1. если я правильно понимаю, то вы предлагаете создать ссылку (в Spring Data это делается с помощью @DBRef). Как именно вы тогда обрабатываете второй вариант использования? Можете ли вы вообще прикрепить Java-код?

2. Я не предлагаю DBRef. Я предлагаю простое строковое свойство, которое содержит идентификатор Монго. Затем на другом прикладном уровне вы можете заполнить свои объекты ответов полными документами отдела после выполнения всех запросов.

3. хорошо, спасибо. Я попробую. Не могли бы вы предложить, как именно реализовать это в Java Spring?

4. Учитывая, что вы используете данные Spring, у вас, вероятно, будут DepartmentRepository и EmployeeRepository. Вам нужно будет координировать вызовы для них обоих. Сначала вы можете использовать findAll() в EmployeeRepository, а затем на основе идентификаторов отдела, которые вы получаете от объектов Employee, вы можете использовать метод findAllById() DepartmentRepository. на основе обоих результатов вы можете затем создать свой ответ API.

5. @lot: вы абсолютно правы! Сила MongoDBs заключается в обработке, поиске, фильтрации автономных документов и определенно не в имитации реляционных баз данных. Например. в прошлом проекте мы использовали MongoDB как своего рода постоянный кэш, который можно эффективно фильтровать по сравнению с самодельным кэшем в памяти.