SoftInstigate / restheart

Rapid API Development with MongoDB
https://restheart.org
GNU Affero General Public License v3.0
807 stars 171 forks source link

Implement insertMany ordered option #289

Closed SzabKel closed 6 years ago

SzabKel commented 6 years ago

Currently, it is not possible to do a batch insert and ignore kind of operation through restheart. What I mean is, you can define an ordered, boolean type argument if you work with Mongo directly. Which Excluding Write Concern errors, ordered operations stop after an error, while unordered operations continue to process any remaining write operations in the queue.

This is extremely useful, if you want duplicate excluding inserts. You can just define a unique index on a field/fields and an unordered insertMany can process batch inserts without actually duplicating documents.

Example java code:

public void insert(List<DocumentTreeJsonDTO> treeJsonDTOs) {
    mongoClient = new MongoClient("....", 27017);
    database = mongoClient.getDatabase("....");
    docTreeCollection = database.getCollection("document-tree");

    ObjectMapper objectMapper = new ObjectMapper();

    List<Document> collect = treeJsonDTOs.stream()....;

    InsertManyOptions imo = new InsertManyOptions();
    imo.ordered(false);

    docTreeCollection.insertMany(collect, imo);

}

Edit: I think, it still throws an exception if an error occurs (but will insert the documents it can)

ujibang commented 6 years ago

done! https://github.com/SoftInstigate/restheart/commit/cae849b4b006241db3d771d462b028c8f702e91e

bulk writes now always uses order=false option.

For instance the following response shows that a new document was inserted and the document with index=0 in the array produced an error (eg duplicate key):

{
    "_errors": [
        {
            "httpStatus": 500,
            "index": 0,
            "message": "Error handling the request, see log for more information",
            "mongodbErrorCode": 11000
        }
    ],
    "_links": {
        "rh:newdoc": [
            {
                "href": "/db/issue289/5b0fb25b1ec483f98a2896c2"
            }
        ]
    },
    "deleted": 0,
    "inserted": 1,
    "matched": 0,
    "modified": 0
}
SzabKel commented 6 years ago

It's not like I am complaining, because it fits my use-case, but won't this break previously implemented clients, if they expect the bulk operation to fail as a whole? Specifying a boolean parameter in url seems like a correct solution (as you mentioned in Gitter).

(Mongo also defaults to ordered)

ujibang commented 6 years ago

well, this is why we have versioned releases :)

in any case the bulk operation does not fail as a whole (it is not atomic), it just stops on the first error. this is why it seems more correct to us not stopping and report back errors in the response, if any.

SzabKel commented 6 years ago

@ujibang Yeah, true, it will not rollback anyway. Thank you!