retrieve array from mongodb using java with mongodb api
Asked Answered
G

4

8

I understand that there are many questions which as for the same and they are answered well. The problem is all those questions use MongoDBObject, MongoDBList to retrieve arrays. My problem is I am using http://api.mongodb.org/java/3.0/index.html?overview-summary.html api and I am having hard time retrieving array and adding elements to it. I have to use MongoCollection, MongoDatabase and MongoClient. I am trying to solve an assignment from mongodb course. The problem statement is to find an array and update it in mongod.

Here is what I have tried

      Document post = null; Bson filter = new Document("permalink",
      permalink); Bson projection = new Document("comments", true);
      List<Document> comments = postsCollection.find(filter)
      .projection(projection).into(new ArrayList<Document>());
      System.out.println(comments);

      post = postsCollection.find(Filters.eq("permalink",
      permalink)).first();

      Document newComment = new Document();

      newComment.append("author", name); newComment.append("body", body);
      if (email != null && (!email.equals(""))) {
      newComment.append("email", email); }

      comments.add(newComment);

      Bson filter2 = new Document("_id", post.get("_id"));
      System.out.println(comments); post =
      postsCollection.find(filter).first();

      postsCollection.updateOne(filter2, new Document("$unset",new
      Document("comments",true))); postsCollection.updateOne(filter2, new
      Document("$set", new Document( "comments", comments)));

This does not create a new comment. Instead, it creates another comments array in comments array itself. THe array should be updated in student

Here is the json data

{
"_id" : ObjectId("55d965eee60dd20c14e8573e"),
"title" : "test title",
"author" : "prasad",
"body" : "test body",
"permalink" : "test_title",
"tags" : [ 
    "test", 
    "teat"
],
"date" : ISODate("2015-08-23T06:19:26.826Z"),
"comments" : [ 
    {
        "_id" : ObjectId("55d965eee60dd20c14e8573e"),
        "comments" : [ 
            {
                "_id" : ObjectId("55d965eee60dd20c14e8573e"),
                "comments" : []
            }, 
            {
                "author" : "commented",
                "body" : "something in comment",
                "email" : "[email protected]"
            }
        ]
    }, 
    {
        "author" : "commented",
        "body" : "something in comment",
        "email" : "[email protected]"
    }
]

}

Gustavo answered 23/8, 2015 at 6:39 Comment(2)
What is the question? You title talks about retrieving and the rest seems to talk about updating, so which is it? What are you actually trying to do here? Is it adding new comments to the array? I also really don't see much justification for ignoring other answers that likely exist for this. Simply substitute DBObject for Document in most cases. And in the few ( not valid for here that I can see ) where DBList is mentioned, then you probably want Arrays.asList() in some variant most of the time.Barbette
Thanks for reply. I would like to update the array but first i need to retrieve it. Now using DBCursor, we can do it as mentioned in other answers. But how can i update an array using the method provided above?Gustavo
W
5

You need not write to this much code. Please check following code,

 public void addPostComment(final String name, final String email, final String body,
                           final String permalink) {
   Document post = findByPermalink(permalink);
   List<Document> comments = null;
   Document comment = new Document();
   if(post != null){
        comments = (List<Document>)post.get("comments");
        comment.append("author",name).append("body", body);

        if(email != null){
            comment.append("email", email);
        }
        comments.add(comment);
        postsCollection.updateOne(new Document("permalink",permalink), 
                                new Document("$set",new Document("comments",comments)));

        }
}
Warnock answered 23/8, 2015 at 9:23 Comment(1)
awesome, thanks man. I was trying to get the comments from database, from your code I came to know we can directly retrieve it from the post document once we get it from database. Thanks a lot. Can we connect on linkedIn or gmail?Gustavo
C
9

To avoid unchecked casts and linter warnings, along with writing your own loop, use the libary's get(final Object key, final Class<T> clazz) method:

List<Document> comments = posts.get("comments", docClazz)

where docClazz is something that you create once:

final static Class<? extends List> docClazz = new ArrayList<Document>().getClass();
Corsage answered 30/3, 2017 at 18:36 Comment(1)
This is elegant solutionMinnieminnnie
W
5

You need not write to this much code. Please check following code,

 public void addPostComment(final String name, final String email, final String body,
                           final String permalink) {
   Document post = findByPermalink(permalink);
   List<Document> comments = null;
   Document comment = new Document();
   if(post != null){
        comments = (List<Document>)post.get("comments");
        comment.append("author",name).append("body", body);

        if(email != null){
            comment.append("email", email);
        }
        comments.add(comment);
        postsCollection.updateOne(new Document("permalink",permalink), 
                                new Document("$set",new Document("comments",comments)));

        }
}
Warnock answered 23/8, 2015 at 9:23 Comment(1)
awesome, thanks man. I was trying to get the comments from database, from your code I came to know we can directly retrieve it from the post document once we get it from database. Thanks a lot. Can we connect on linkedIn or gmail?Gustavo
E
4

This is much simplified here!

version - mongo-java-driver-3.12.5.jar

comments = post.getList("comments", Document.class);
Eveliaevelin answered 29/6, 2020 at 7:14 Comment(0)
T
0

If you're forced to use older version of mongo driver and you can't use the method the MKP has mentioned, then you can copy the method itself.

Here it is as a Kotlin extension

import org.bson.Document
import java.lang.String.format

fun <T> Document.getList(key: String, clazz: Class<T>, defaultValue: List<T>): List<T> {
    val list = this.get(key, List::class.java)
    if (list == null) {
        return defaultValue
    }
    list.forEach {
        if (!clazz.isAssignableFrom(it!!::class.java)) {
            throw ClassCastException(format("List element cannot be cast to %s", clazz.getName()))
        }
    }
    return list as List<T>
}
Tita answered 4/8, 2021 at 13:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.