W W
W W

Reputation: 789

How to convert from Mongo Document to java Set<String>?

I've saved Set<String> into mongodb as array and after that I want to load it again into Set<String>. How to do this?

My try returns exception:

package Database;

import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Projections.fields;
import static com.mongodb.client.model.Projections.include;

import java.util.HashSet;
import java.util.Set;

import org.bson.Document;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;

public class StackOverflow {

    public static void main(String[] args) {

        // insert something to mongo:
        final String URI = "mongodb://localhost:27017";
        final String DB = "StackOverflowQuestion";
        final String COLLECTION = "eqDoesntExcist";

        MongoClientURI connection = new MongoClientURI(URI);
        MongoClient mongo = new MongoClient(connection);
        MongoDatabase database = mongo.getDatabase(DB);
        MongoCollection<Document> collection = database.getCollection(COLLECTION);

        Set<String> namesOfTroysKids = new HashSet<>();
        namesOfTroysKids.add("Paul");
        namesOfTroysKids.add("Jane");
        namesOfTroysKids.add("Mark");
        namesOfTroysKids.add("Ivona");

        Document doc = new Document("name", "Troy").append("height", 185).append("kids", namesOfTroysKids);
        collection.insertOne(doc);

        // read something from mongo
        FindIterable<Document> findIt = collection.find(eq("name", "Troy")).projection(fields(include("kids")));
        Document d = findIt.first();

        Set<String> kids = (Set<String>) d; // ERROR !!!
        ///Exception in thread "main" java.lang.ClassCastException: org.bson.Document cannot be cast to java.util.Set
        //at Database.StackOverflow.main(StackOverflow.java:45)

    }

}

There was method toArray() but it is for DBObject which is depreciated.

Upvotes: 1

Views: 6635

Answers (2)

JohnC
JohnC

Reputation: 737

The document returned by your query is:

{
   "_id": {
      "$oid": "_id_value_"
   },
   "kids": [
      "Mark",
      "Ivona",
      "Paul",
      "Jane"
   ]
}

That obviously can not be implicitly coerced into a set. Its now just a matter of obtaining the kids from the document as a list and instantiating a Set from it:

public static void main(String [] args) throws Exception  {
    final String URI = "mongodb://localhost:27017";            
    final String DB = "StackOverflowQuestion";
    final String COLLECTION = "eqDoesntExcist";

    MongoClientURI connection = new MongoClientURI(URI);
    MongoClient mongo = new MongoClient(connection);
    MongoDatabase database = mongo.getDatabase(DB);
    MongoCollection<Document> collection = database.getCollection(COLLECTION);

    Set<String> namesOfTroysKids = new HashSet<>();
    namesOfTroysKids.add("Paul");
    namesOfTroysKids.add("Jane");
    namesOfTroysKids.add("Mark");
    namesOfTroysKids.add("Ivona");

    Document doc = new Document("name", "Troy").append("height", 185).append("kids", namesOfTroysKids);
    collection.insertOne(doc);

    // read something from mongo
    FindIterable<Document> findIt = collection.find(Filters.eq("name", "Troy")).projection(Projections.include("kids"));
    Document d = findIt.first();

    System.out.println("doc: " + d.toJson());

    List<String> kidsList = (List<String>) d.get("kids", List.class);

    Set<String> kidsSet = new HashSet<>(kidsList);

    System.out.println("kids: " + kidsSet);
}

Upvotes: 2

Scott
Scott

Reputation: 174

Basically an Iterable type is something that is meant to loop through. If you open a cursor using the Iterable type the only way to assign it to a java data type is to grab one iteration. You have done this by using the first method which will grab the first document returned by your query, note that if that is your intention you can use sort to control which Document is returned.

Below is the code. When i do this i generally do whatever i need to with the data one by one unless i need the entire dataset before i start my processing.

Set<String> kids = new Set<String>;    
for(Document kidDoc :  collection.find(eq("name", "Troy"))){
        kids.add(kidDoc.getString("kids")))
}

Upvotes: 1

Related Questions