2013-07-05 38 views
1

3天前我开始学习MongoDB,在做练习时,服务器出现了一些意外的行为。奇怪的MongoDB行为

的行使要求写一个小程序,从具有以下结构的文档中删除最低功课成绩(这个文件是学生集合内):

{ 
    "_id": 10, 
    "name": "Demarcus Audette", 
    "scores": [ 
     { 
      "type": "exam" 
      "score": 47.42086 

     }, 
     { 
      "type": "quiz" 
      "score": 44.83456 

     },{ 
      "type": "homework" 
      "score": 39.0178956 

     },{ 
      "type": "homework" 
      "score": 14.578344 

     } 
    ] 
} 

不管怎么说,写程序我意外地犯了一个错误。这是我写的

def removeHW(hw): 
    # establish a connection to the database 
    connection = MongoClient("localhost", 27017) 

    # get a handle to the school database 
    db = connection.school 
    students = db.students 

    # extract the scores into a list 
    scores = [] 
    for i in range(1, len(hw)): 
     scores.append(hw[i]["score"]) 

    # Now remove the lowest score from the database 
    query = {"_id": hw[0], "scores.score": min(scores),"scores.type": "homework"} 

    try: 
     students.remove(query) 
    except: 
     print "Unexpected error:", sys.exc_info()[0] 
程序

我的程序背后的逻辑是,之后我提取含有从学生两个家庭作业和_id词典列表集合,我遍历所有的字典,并把它传递给removeHW()函数。

我犯的错误是,我写道:

query = {"_id": hw[0], "scores.score": min(scores),"scores.type": "homework"} 
students.remove(query) 

当我写了下面的(这是正确的解决方案):

query = {"_id": hw[0], "scores.type": "homework"} 
students.update(query, {"$pull": {"scores": {"score" : min(scores)}}}) 

是的,我知道到现在为止似乎一切都安然无恙。我遇到的问题是,使用第一个解决方案(错了),当MongoDB中删除了所有来自学生收集的文件,并创建了一个新的集合包含所有从学生子文档得分集合,除了一个我想要的去除(功课最低的作业)。我发现这种行为非常奇怪,因为我没有使用过NoSQL数据库的经验,所以我想知道是什么导致MongoDB做到这一点,为什么。

如果有人能帮助我理解,请做。我会永远感谢你。

+0

“永远感激?” :)这是一个很长的时间。你确定所有的文件都被删除了吗? (“学生”系列中有多少人)?'_id'应该将其限制为一个文档。而且,鉴于您提供的代码中没有插入/更新,我不明白它会如何完成您所说的内容。 – WiredPrairie

+0

是的,我确定,学生收藏中有200个文档,mongo创建的分数集合的结构如下:{{“_id”:10,“name”:“Demarcus Audette”,“type”: “考试”,“分数”:44.654},{“_id”:10,“name”:“Demarcus Audette”,“type”:“家庭作业”,score:45.456},...},我告诉你这是我见过的最奇怪的事 – Codejunky

+0

你通过移除HW的结构是什么? – innoSPG

回答

1

由于给定学生的所有数据都存储在同一文档中,因此这种行为是完全正常的。发生的事情是: 您的收藏中的每个文档都有评分类型作业的最低分数。所以每个文档都符合条件并且是删除。

在第二个选项中,您采取了拉一个分数的预防措施。但是,仍然不能确定总是成功。假设测验或考试的分数等于作业分数的最小值。你也可以拉那个。除了检查您是否以最低分进行评估之外,还应该检查您正在进行的评估是否属于作业类型。

查询部分(“scores.type”:“homework”)只确保您只更新在作业中至少有一个分数的学生。如果有一个没有功课的学生,你可能会遇到分钟问题;我不熟悉python。

+0

感谢您的回答,但我应该指出,min函数仅比较homework分数,因为hw(这是一个列表)只包含学生的_id和两个包含学生作业的字典(我之前提出的)分数。 – Codejunky

+0

不客气。另一点,你正在计算完美的分钟。但是由于所有的分数都在同一个阵列中,所以作业的分数可以加快测验或考试的分数。在这种情况下,你会把他们全部拉出来。尝试添加一个具有相同得分的文档。 – innoSPG

+0

好吧,我明白你的意思了,我认为你是对的。再次感谢。 – Codejunky

0

对于删除或更新操作的响应,MongoDB不会创建“分数”集合。特别是,更新或从“学生”集合中删除将不会创建“分数”集合。

当你插入到集合中,或插入到集合中或显式调用create_collection时,MongoDB创建一个集合。