Programming Monkey
Programming Monkey

Reputation: 87

Trying to update a document using MongoDB Java Driver

Thank you

Setup

What I want to do

Example Document

// the document that I am trying to find in db
{
  "_id":"5de6af7cfa42833bd9849477",
  "name":"Richard Koba",
  "skills":[]
}

// the document that I have
{
  "name":"Richard Koba",
  "skills":[jump, dance, sing]
}

// final result in db
{
  "_id":"5de6af7cfa42833bd9849477",
  "name":"Richard Koba",
  "skills":[jump, dance, sing]
}

What I am doing now

  // finding a document with same "name" field as input doc and update it with doc
  public MongoCollection updateDocument(Document doc, String colName) {
    MongoCollection collection;

    // make sure collection exist
    try {
      collection = connectCollection(colName); // returns MongoCollection Obj
    } catch (CollectionNotFoundException e) {
      MessageHandler.errorMessage(e.getMessage());
      return null;
    }

    // trying to find the document.
    if (collection.find(eq("name", doc.get("name"))).first() == null) {
      // if document not found, insert a new one
      collection.insertOne(doc);
    } else {
      // if the document found, replace/update it with the one I have
      collection.replaceOne(eq("name", doc.get("name")), doc);
    }

    return collection;
  }

What I found about my false solution

  1. collection.find(eq("name", doc.get("name"))).first() never returns null.
  2. Java only tells me it returns an Object. MongoDB Documentation tells me it is a TResult, which point back to MongoIterable<TResult>. I am stuck here.
  3. the code outcome is that none of the documents is inserted/updated in the end.

Reference

Upvotes: 2

Views: 1208

Answers (2)

prasad_
prasad_

Reputation: 14287

I tried some code and this works fine. This is not much different from your code.

Created a document from mongo shell:

MongoDB Enterprise > db.users.findOne()
{
        "_id" : "5de6af7cfa42833bd9849477",
        "name" : "Richard Koba",
        "skills" : [ ]
}

My Java Code:

// Test input documents
private Document doc1 = new Document()
                           .append("name", "Richard Koba")
                           .append("skills", Arrays.asList("jump", "dance", "sing"));
private Document doc2 = new Document()
                            .append("name", "Richard K")
                            .append("skills", Arrays.asList("sings"));

When doc1 is passed to the following method the result is: "### Doc FOUND". And, with doc2 the result is "### Doc NOT found".

private void checkDocument(Document doc) {

    MongoClient mongoClient = MongoClients.create("mongodb://localhost/");
    MongoDatabase database = mongoClient.getDatabase("javadb");
    MongoCollection<Document> collection = database.getCollection("users");

    if (collection.find(eq("name", doc.get("name"))).first() == null) {

        System.out.println("### Doc NOT found");
    } 
    else {
        System.out.println("### Doc FOUND");
    }
}

I also tried this, with the same results.

Document d = collection.find(eq("name", doc.get("name"))).first();
if (d == null) { // ... }

I also tried this; works fine too.

if (collection.find(queryFilter).iterator().tryNext() == null) { // ... }


I think there might be some other issue with your code or the database / collection. Some debugging and testing with new data might reveal the real issue.

  • Did you check if the document already exists in the collection, from mongo shell or Compass tools?
  • Are you using the right database and collection names?
  • After each test run are you verifying the data in the database if it is updated / inserted?



collection.find(eq("name", doc.get("name"))).first() never returns null.

With the code I posted above, the find query did return null when the users collection was empty.

Upvotes: 1

chakwok
chakwok

Reputation: 1040

  1. collection.find() return an array of documents. What you actually want here is collection.findOneAndUpdate()

  2. After you get a TDoucment object from findOneAndUpdate, you can use a ObjectMapper e.g.jackson to map it back to a java object

Upvotes: 0

Related Questions