首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Mongodb Java:根据元素的特定条件移除文档中嵌入数组的元素

Mongodb Java:根据元素的特定条件移除文档中嵌入数组的元素
EN

Stack Overflow用户
提问于 2015-01-21 23:37:47
回答 13查看 8.5K关注 0票数 0

我有一个学生文档列表,其结构如下:

代码语言:javascript
复制
{
    "_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
            }
    ]
}

如你所见,每个学生都有一个包含4个分数的列表。我需要删除每个学生文档的最低“家庭作业”分数。每个学生有2个条目表示"homewok“类型的分数(4个元素数组中的最后2个条目)。分数类型的模式和顺序是一致的,并且对所有学生都具有相同的模式,感谢您的帮助。

这就是我到目前为止一直在努力实现的:

代码语言:javascript
复制
    DBCursor cursor = collection.find();

    try {

        while(cursor.hasNext()) {
           BasicDBObject doc = (BasicDBObject) cursor.next();
           BasicDBList scoreList =  (BasicDBList) doc.get("scores");

           BasicDBObject hw1 = (BasicDBObject) scoreList.get("2");
           double hw1Score = hw1.getDouble("score");

           BasicDBObject hw2 = (BasicDBObject) scoreList.get("3");
           double hw2Score = hw2.getDouble("score");

           if (hw1Score > hw2Score) {
               BasicDBObject update = new BasicDBObject("scores.score", hw2Score);               
               collection.update(doc, new BasicDBObject("$pull",update));                                                  
           } else {
               BasicDBObject update = new BasicDBObject("scores.score", hw1Score);

               collection.update(doc, new BasicDBObject("$pull",update));                                  
           }
           System.out.println(doc);
        }

    } finally {
       cursor.close();
    }


}
EN

回答 13

Stack Overflow用户

发布于 2018-08-24 04:35:22

这里的所有答案都很棒。我只想补充一点,如果有人想要使用Java操作符(从driver v3.1开始),那么他可以这样做,而不是使用"$pull“操作符:

代码语言:javascript
复制
...
Bson studentFilter = Filters.eq( "_id", doc.get("_id") );
Bson delete = Updates.pull("scores", new Document("score", lowestHomework).append("type", "homework"));
collection.updateOne(studentFilter, delete);

我觉得它更优雅。所以我的完整答案是:

代码语言:javascript
复制
public static void main(String[] args) {
    MongoClient client = new MongoClient();
    MongoDatabase database = client.getDatabase("school");
    MongoCollection<Document> collection = database.getCollection("students");

    List<Document> homeworks = collection.find()
        .into(new ArrayList<Document>());

    for(Document doc : homeworks)
    {
        ArrayList<Document> scores = (ArrayList<Document>) doc.get("scores");
        //iterate over the scores of each student (there are 4 scores: quiz, exam and 2*homework)
        double lowestHomework = Double.MAX_VALUE;
        for(Document embeddedDoc : scores)
        {
            if(embeddedDoc.getString("type").equals("homework"))
            {
                Double score = embeddedDoc.getDouble("score");
                if(score < lowestHomework)
                {
                    lowestHomework = score;
                }
            }
        }
        Bson studentFilter = Filters.eq( "_id", doc.get("_id") );
        Bson delete = Updates.pull("scores", new Document("score", lowestHomework).append("type", "homework"));

        collection.updateOne(studentFilter, delete);
    }

    client.close();
}
票数 5
EN

Stack Overflow用户

发布于 2015-01-22 12:18:27

我知道这不是最好的解决方案(更好的方法是对每个文档的作业分数进行排序,然后将数组大小限制为3)。但这也是可行的:)

代码语言:javascript
复制
     try {

        while(cursor.hasNext()) {
           BasicDBObject doc = (BasicDBObject) cursor.next();
           BasicDBList scoreList =  (BasicDBList) doc.get("scores");              
           doc.remove("scores");

           BasicDBObject hw1 = (BasicDBObject) scoreList.get("2");
           double hw1Score = hw1.getDouble("score");

           BasicDBObject hw2 = (BasicDBObject) scoreList.get("3");
           double hw2Score = hw2.getDouble("score");

           if (hw1Score > hw2Score) {                                                  
               scoreList.remove(3);                     
           } else {
               scoreList.remove(2);                                          
           }
           doc.put("scores",scoreList);  
           collection.save(doc);
           System.out.println(doc);
        }

    } finally {
       cursor.close();
    }        


}

}

票数 2
EN

Stack Overflow用户

发布于 2016-08-19 23:49:59

试试这个;我假设最高分是100分:

代码语言:javascript
复制
for (Document document : cursor) {
    ArrayList<Document> list =  (ArrayList<Document>) document.get("scores");
    double score = 100;
    for (Document doc : list) {
        if(doc.getString("type").equals("homework")){
            if(doc.getDouble("score") < score){
                score = doc.getDouble("score");
            }
        }
    }
    BasicDBObject update = new BasicDBObject("scores", new BasicDBObject("score", score).append("type", "homework"));
    collection.updateOne(document, new BasicDBObject("$pull", update));     
    }
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28071078

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档