在mongoDb中查询和分组?

时间:2011-07-15 20:44:51

标签: mongodb mapreduce grouping nosql

第1部分:

我有(学生)收藏:

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

我试图只从中获取两个键:

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

所以我需要消除年龄和gpa只有名字和studentId,我怎么能这样做?

第2部分:

然后我有'主题'集合:

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

我需要匹配/组合以前的键(在第1部分中)和正确的studentId,所以我最终会得到这样的结果:

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

 }

我怎样才能做到这一点并且是想要获得结果的正确方法?我试着阅读有关group和mapReduce的内容,但我没有找到一个明确的例子。

2 个答案:

答案 0 :(得分:4)

要回答您的第一个问题,您可以这样做:

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

第一个{}是限制查询,在这种情况下包括整个集合。后半部分指定1或0的键,具体取决于您是否需要它们。不要在一个查询中混合包含和排除。除了一些特殊情况,mongo不接受它。

你的第二个问题更难。您要求的是加入,而mongo不支持。无法在studentId上连接两个集合。你需要找到你想要的所有学生,然后使用这些studentIds找到所有匹配的科目。然后,您需要在自己的代码中合并两个结果。你可以通过你正在使用的任何驱动程序来做到这一点,或者你可以在shell本身的javascript中执行此操作,但不管怎样,你必须将它们与你自己的代码合并。

编辑: 这是一个如何在shell中执行此操作的示例,其输出将转到名为“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”集合并使用此shell脚本定期重新填充它。然后你的代码可以直接从“out”查询。如果数据经常发生变化,您可能希望动态地在代码中进行合并。

另一个,可能更好的选择是将“主题”数据包含在“学生”集合中,反之亦然。这将导致更加mongodb友好的结构。如果经常遇到这个加入问题,mongo可能不是可行的方法,关系数据库可能更适合您的需求。

答案 1 :(得分:1)

Mongo的find()运算符允许您在结果中包含或排除某些字段

查看文档中的Field Selection了解详情。你可以这样做:

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" }, ... ]
}