2011-07-15 22 views
3

1部分:在mongoDb中查询和分组?

我已经(学生)收集:

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

即时通讯试图从中得到的只有两个键:

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

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

第2部分:

然后,我有“主题”集合:

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

我需要匹配/结合前面的键(在第1部分)用正确的studentId所以我将结束这样的事情:

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

} 

我怎么能这样做,是正确的方式来想想得到的结果?我试图阅读关于组和mapReduce,但我没有找到一个明确的例子。

回答

4

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

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

第{}在是限制的查询,在这种情况下,包括整个集合。后半部分指定带1或0的键,具体取决于您是否希望返回键。不要在一个查询中混用include和exclude。除了一些特殊情况,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}); 
     } 
    ); 
    } 
); 

如果不经常更改的所有数据,你可能只是下降的“走出去”的收集和使用此shell脚本定期重新填充它。然后你的代码可以直接从“out”查询。如果数据确实频繁更改,那么您将需要在代码中进行合并。

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

+1

你也可以使用[$在运营商(http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24in),以减少查询的数量需要生成'out'表。这在高负载下尤其重要,或者在通过网络查询往返时间可能成为大量学生的因素时尤为重要。 – dcrosta

1

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