2013-07-05 73 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創建一個集合。