Compare array elements,remove the one with the low

2019-04-16 17:41发布

There are 200 documents in school db. I must remove each document which has "type":"homework" and the lowest score.

    {
        "_id" : 0,
        "name" : "aimee Zank",
        "scores" :
        [
            {
                "type" : "exam",
                "score" : 1.463179736705023
            },
            {
                "type" : "quiz",
                "score" : 11.78273309957772
            },
            {
                "type" : "homework",
                "score" : 6.676176060654615
            },
            {
                "type" : "homework",
                "score" : 35.8740349954354
            }
        ]
    }

For example,here

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

must be removed as score = 6.6 < 35.8

I sorted all the documents like this:

db.students.find({"scores.type":"homework"}).sort({"scores.score":1})

But I do not know how then to remove the doc having the lowest score and type:homework??? NOTE: how to solve it by not using aggregation method? E.g., by sorting and then updating.

2条回答
Rolldiameter
2楼-- · 2019-04-16 18:21
import pymongo
import sys

# connnecto to the db on standard port
connection = pymongo.MongoClient("mongodb://localhost")

db = connection.school           # attach to db
students = db.students        # specify the colllection


try:

        cursor = students.find({})
        print(type(cursor))
        for doc in cursor:
            hw_scores = []
            for item in doc["scores"]:
                if item["type"] == "homework":
                    hw_scores.append(item["score"])
            hw_scores.sort()
            hw_min = hw_scores[0]
            #students.update({"_id": doc["_id"]},
             #           {"$pull":{"scores":{"score":hw_min}}})


except:
    print ("Error trying to read collection:" + sys.exc_info()[0])
查看更多
趁早两清
3楼-- · 2019-04-16 18:37

This can be done in a couple of steps. The first step is to grab a list of the documents with the minimum score by using the aggregation framework with $match, $unwind and $group operators that streamlines your documents to find the minimum score for each document:

lowest_scores_docs = db.school.aggregate([ 
    { "$match": {"scores.type": "homework"} },
    { "$unwind": "$scores" },  { "$match": {"scores.type": "homework"} },
    { "$group": { "_id":"$_id", "lowest_score": {"$min": "$scores.score" } } } ] )

The second step is to loop through the dictionary above and use the $pull operator in the update query to remove the element from the array as follows:

for result in lowest_scores_docs["result"]:
    db.school.update({ "_id": result["_id"] }, 
        { "$pull": { "scores": { "score": result["lowest_score"] } } } )
查看更多
登录 后发表回答