12

According to the javaDoc, getN() method of WriteResult class in MongoDB-java returns the number of documents updated in the opertion. But it always returns zero, even if the document is inserted correctly.

Why so? or I understood it wrongly?

vivek_jonam
  • 3,237
  • 8
  • 32
  • 44
  • It works properly. Which mongo version you are using? Are the documents inserted properly in the DB after this operation? – Buchi Feb 28 '13 at 22:27
  • 1
    yes the documents were inserted correctly! Mongo version: 2.2.2 – vivek_jonam Mar 01 '13 at 05:43
  • 1
    I too am finding the same thing. It is returning 0. See here as well http://stackoverflow.com/questions/10662858/mongodb-java-api-writeresultgetn – btiernay Mar 22 '13 at 15:23
  • Can you add a failing test, and example data to show the problem? – Trisha Jul 05 '13 at 09:28
  • 2
    @Trisha Its not a wrong behavior. The getN() returns the documents count only on update, for insert it returns 0 always. – vivek_jonam Jul 05 '13 at 11:24

3 Answers3

10

I was under the impression that this was the normal MongoDB behaviour, and has nothing to do with the Java driver.

The only thing I can find in the documentation is this:

getLastError.n reports the number of documents updated or removed, if the preceding operation was an update or remove operation.

An insert being neither an update nor a remove, n doesn't seem to be specified and 0 is as good a default value as any. You can check it easily enough in the mongo shell:

> db.test.insert({_id: 'test'})
> db.getLastErrorObj()
{ "n" : 0, "connectionId" : 7, "err" : null, "ok" : 1 }

Unless I'm mistaken, it's not really an issue: ask yourself under which circumstances the insert would fail (other than, say, a connection failure). The only one I can think of is a unicity constraint violation, which would result in an exception. So almost by definition, the fact that you receive a WriteResult instance at all means the operation was successful and a document was inserted.

A couple of notes:

  • my previous argument hinges on your WriteConcern being high enough that errors are reported. If you're using WriteConcern.NONE, for example, no exception will ever be raised.
  • if the number of updated documents is an absolute must for you, you can always use save instead of insert. Not very clean, but it behaves the way you seem to expect.
Nicolas Rinaudo
  • 6,068
  • 28
  • 41
  • 2
    I think there is an issue with this behaviour, because the Javadoc for `getN()` says "*Gets the "n" field, which contains the number of documents affected in the write operation.*. If you do an [unordered insert](http://docs.mongodb.org/manual/reference/method/db.collection.insert/#perform-an-unordered-insert), it is valuable to know if anything changed, and using `getN()` then introduces a bug in your application by always returning 0. A sensible solution (besides correcting the Javadoc) could be to make `getN()` throw an exception for inserts, or not include the method in the first place! – Zero3 Aug 11 '15 at 18:31
  • @Zero3 unordered inserts are more recent than this answer. Additionaly, WriteResult includes the number of inserted documents since 2.6, I believe you just need to call getField with the right name. Finally, the most recent javadoc says nothing about what the n field is, it just says 'get the n field'. While that's not terribly useful, it's hardly incorrect. And if you look at the official mongodb documentation for the n field, it's pretty clear that inserts will yield an n value of 0 - perhaps not the best behaviour, but the correct one according to specs. Just use the correct field. – Nicolas Rinaudo Aug 11 '15 at 19:19
  • [WriteResult](http://api.mongodb.org/java/current/com/mongodb/WriteResult.html) has no such functionality in the latest version, and the description of `getN()` is exactly as I wrote. Check for yourself :). – Zero3 Aug 11 '15 at 19:51
  • Sure. [WriteResult](http://docs.mongodb.org/manual/reference/method/db.collection.insert/#successful-results): _Upon success, the WriteResult object contains information on the number of documents inserted_. You're right about the `getN` bit, I'd mistakenly assumed that the latest javadoc version was 2.6. – Nicolas Rinaudo Aug 11 '15 at 19:57
  • Right, so for unordered inserts, you want to use [BulkWriteOperation](https://api.mongodb.org/java/3.1/com/mongodb/BulkWriteOperation.html), obtained through [initializeUnorderedBulkOperation](https://api.mongodb.org/java/3.1/com/mongodb/DBCollection.html#initializeUnorderedBulkOperation--), which eventually yields a [BulkWriteResult](https://api.mongodb.org/java/3.1/com/mongodb/BulkWriteResult.html), which has a [getInsertedCount](https://api.mongodb.org/java/3.1/com/mongodb/BulkWriteResult.html#getInsertedCount--) method. – Nicolas Rinaudo Aug 11 '15 at 20:02
  • Your WriteResult link is to the `mongo` shell documentation, but as you can see in the Java driver's [WriteResult](http://api.mongodb.org/java/current/com/mongodb/WriteResult.html) documentation, that information is not available. The original question is about the Java driver, not the shell. The newer bulk operations do indeed provide a way, but that does not explain the problem pointed out in the original question about the plain insert API. It is good to know there is an alternative though! – Zero3 Aug 11 '15 at 21:47
5

Note that regardless of what the MongoDB documentation states, the WriteResult.getN() method always returns 0 for insert using the Java driver, regardless of the number of objects inserted. The source code for setting the "n" field in the 2.12.3 of the Java driver:

if (type == INSERT) {
  commandResult.put("n", 0);
} else if (type == REMOVE) {
  commandResult.put("n", bulkWriteResult.getRemovedCount());
} else if (type == UPDATE || type == REPLACE) {
  commandResult.put("n", bulkWriteResult.getMatchedCount() + bulkWriteResult.getUpserts().size());
  if (bulkWriteResult.getMatchedCount() > 0) {
    commandResult.put("updatedExisting", true);
  } else {
    commandResult.put("updatedExisting", false);
  }
  if (!bulkWriteResult.getUpserts().isEmpty()) {
    commandResult.put("upserted", bulkWriteResult.getUpserts().get(0).getId());
  }
}

But errors are correctly reported via Exceptions. For example, a MongoException will be thrown when inserting a document that violates a unique index, if WriteConcern specified is at least the ACKNOWLEDGED

wbdarby
  • 1,129
  • 12
  • 12
1

You may also want to check http://docs.mongodb.org/manual/core/write-concern/

The dafault behaviour is not to use the "safe" write concern

Mario Trucco
  • 1,933
  • 3
  • 33
  • 45