Запрашивать и группировать в mongoDb? - PullRequest
3 голосов
/ 16 июля 2011

Часть 1:

У меня есть коллекция (студент):

 {
    sname : "",
    studentId: "123"
    age: "",
    gpa: "",
 }

Я пытаюсь получить от нее только два ключа:

{
    sname : "",
    studentId: "123"
}

так что мне нужно исключить возраст и гпа, чтобы иметь только имя и имя студента, как я могу это сделать?

Part2:

Тогда у меня есть коллекция 'subject':

{
    subjectName : "Math"
    studentId : "123"
    teacherName: ""
 }

Мне нужно сопоставить / объединить предыдущие ключи (в части 1)с правильным учеником, так что я получу что-то вроде этого:

 {
    sname : "",
    studentId: "123",
    subjectName : "Math" 

 }

Как я могу это сделать, и это правильный способ думать, чтобы получить результат?Я пытался прочитать о группе и mapReduce, но я не нашел четкого примера.

Ответы [ 2 ]

4 голосов
/ 16 июля 2011

Чтобы ответить на ваш первый вопрос, вы можете сделать это:

db.student.find({}, {"sname":1, "studentId":1});

Первый {} в этом запросе ограничения, который в этом случае включает в себя всю коллекцию. Вторая половина определяет ключи с 1 или 0 в зависимости от того, хотите ли вы их вернуть. Не смешивайте include и exclude в одном запросе. За исключением пары особых случаев, Монго не примет это.

Ваш второй вопрос сложнее. То, что вы просите, это объединение, и монго это не поддерживает. Невозможно соединить две коллекции в studentId. Вам нужно будет найти всех учеников, которых вы хотите, а затем использовать эти идентификаторы учеников, чтобы найти все подходящие предметы. Затем вам нужно объединить два результата в ваш собственный код. Вы можете сделать это через любой драйвер, который вы используете, или вы можете сделать это в javascript в самой оболочке, но в любом случае вам придется объединить их с вашим собственным кодом.

Edit: Вот пример того, как вы можете сделать это в оболочке с выводом в коллекцию с именем out.

db.student.find({}, {"sname":1, "studentId":1}).forEach(
  function (st) {
    db.subject.find({"studentId":st.studentId}, {"subjectName":1}).forEach(
      function (sub) {
        db.out.insert({"sname":st.sname, "studentId":st.studentId, "subjectName":sub.subjectName});
      }
    );
  }
);

Если эти данные не так часто меняются, вы можете просто удалить коллекцию "out" и периодически заполнять ее с помощью этого сценария оболочки. Тогда ваш код может запрашивать напрямую из «вне». Если данные часто меняются, вы захотите сделать это в своем коде на лету.

Другой, и, возможно, лучший вариант, это включить данные «предмета» в коллекцию «ученик» или наоборот. Это приведет к более дружественной структуре mongodb. Если вы часто сталкиваетесь с этой проблемой объединения, монго может оказаться не лучшим способом, и реляционная база данных может лучше соответствовать вашим потребностям.

1 голос
/ 16 июля 2011

Оператор find() Монго позволяет включать или исключать определенные поля из результатов

Проверьте Выбор поля в документации для получения дополнительной информации. Вы можете сделать либо:

db.users.find({}, { 'sname': 1, 'studentId': 1 });
db.users.find({}, { 'age': 0, 'gpa': 0 });

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

db.subjects.find({ studentId: 123 });

Или вставьте данные о предметах каждому ученику и извлеките их вместе с документом ученика:

{
    sname : "Roland Browning",
    studentId: "123"
    age: 14,
    gpa: "B",
    subjects: [ { name : "French", teacher: "Mr Bronson" }, ... ]
}
...