Как найти записи с одинаковым значением ключа, назначенным нескольким значениям в MongoDB - PullRequest
1 голос
/ 01 ноября 2019

У меня есть такие данные, как

  • Student |Тема
  • A |Язык
  • A |Математика
  • B |Наука
  • А |Arts
  • C |Биология
  • B |История

и т. Д. ...

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

Я пытался использовать запрос:

$group:{
    _id:"$student",
    sub:"{$addToSet:"$subject"}
},
$match:{
     sub:{$in:["Language","Math"]}
}

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

Спасибо за загрузку.

Сбор данных и ожидаемый результат:

{ Student:"A", Subject:"Language" }, 
{ Student:"A", Subject:"Math" }, 
{ Student:"B", Subject:"Science" }, 
{ Student:"A", Subject:"Arts" }, 
{ Student:"C", Subject:"Biology" }, 
{ Student:"B", Subject:"History" } 

Я хочу получить A в качестве результата.

Ответы [ 2 ]

0 голосов
/ 02 ноября 2019

Вы должны использовать оператор агрегирования, $ setIsSubset . Оператор $ in (агрегат) используется для проверки массива только на значение one . Я думаю, вы думаете о $ in (оператор запроса) ..


Запрос:

db.student_subjects.aggregate( [
{ $group: {
        _id: "$student",
        studentSubjects: { $addToSet: "$subject" }
   } 
},
{ $project: { 
       subjectMatches: { $setIsSubset: [ [ "Language", "Math" ], "$studentSubjects" ] }
   }
},
{ $match: { 
       subjectMatches: true
   } 
},
{ $project: { 
       matched_student: "$_id", _id: 0 
   } 
}
] )

Результат:

{ "matched_student" : "A" }


ПРИМЕЧАНИЯ:

Если вы замените [ "Language", "Math" ] на [ "History" ], вы получите результат: { "matched_student" : "B" }.

Вы также можете попробовать и посмотреть другие операторы множеств (агрегация) , например $allElementsTrue. Используйте лучший, который подходит для вашего приложения.



[РЕДАКТИРОВАТЬ ДОБАВИТЬ]

Пример данных для student_subjects коллекция:

{ "_id" : 1, "student" : "A", "subject" : "Language" }
{ "_id" : 2, "student" : "A", "subject" : "Math" }
{ "_id" : 3, "student" : "B", "subject" : "Science" }
{ "_id" : 4, "student" : "A", "subject" : "Arts" }
{ "_id" : 5, "student" : "C", "subject" : "Biology" }
{ "_id" : 6, "student" : "B", "subject" : "History" }


Результат после каждого этапа:

1-й этап: $group

{ "_id" : "C", "studentSubjects" : [ "Biology" ] }
{ "_id" : "B", "studentSubjects" : [ "History", "Science" ] }
{ "_id" : "A", "studentSubjects" : [ "Arts", "Math", "Language" ] }

2-йЭтап: $project

{ "_id" : "C", "subjectMatches" : false }
{ "_id" : "B", "subjectMatches" : false }
{ "_id" : "A", "subjectMatches" : true }

3-й этап: $match

{ "_id" : "A", "subjectMatches" : true }

4-й этап: $project

{ "matched_student" : "A" }
0 голосов
/ 01 ноября 2019

Вы почти у цели, просто нужно немного настроить ваш конвейер агрегации:

const pipeline = [
  {
    $group:
    {
      _id: '$Student', // Group students by name
      subjects: {
        $addToSet: '$Subject', // Push all the subjects they take uniquely into an array
      },
    },
  },
  {
    // Filter for students who only offer Language and Mathematics
    $match: { subjects: { $all: ['Language', 'Math'], $size: 2 } },
  },
];


db.students.aggregate(pipeline);

Это должно дать выходной массив, подобный этому:

[
  { "_id" : studentName1 , "subjects" : [ "Language", "Math" ] },
  { "_id" : studentName2 , "subjects" : [ "Language", "Math" ] },
  ....
]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...