Add multiple sub-documents in MongoDB

爷,独闯天下 提交于 2019-12-08 07:27:18

问题


I am working on a customer data loader, where customers can have multiple addresses. If the customer is not found, I create it and add the address. If the customer exists, I simply add the new address, like this:

    DBObject findCustomer = new BasicDBObject();
    findCustomer.put("email", custEmail);

    //check for existing customer
    DBObject newCustomer = customerCollection.findOne(findCustomer);

    if (newCustomer == null) {
        //INSERT    
        newCustomer = new BasicDBObject();
        newCustomer.put("firstname", firstname);
        newCustomer.put("lastname", lastname);
        newCustomer.put("email", custEmail);
        newCustomer.put("password", custData.getPassword());
        newCustomer.put("softwaretime", new Date());
    }

    DBObject newAddress = new BasicDBObject();
    City tempCity = new City();
    tempCity = addressData.getCity();

    newAddress.put("type", addressData.getType());
    newAddress.put("line1", addressData.getLine1());
    newAddress.put("line2", addressData.getLine2());
    newAddress.put("city", tempCity.getCity());
    newAddress.put("state", tempCity.getState());
    newAddress.put("postal", tempCity.getZip());
    newAddress.put("country", tempCity.getCountry());

    newCustomer.put("address", newAddress);

    customerCollection.save(newCustomer);

This works for new customers. The problem is that when the customer already exists, the new address overwrites the existing address.

How can I add the new address to the customer, so that it will keep multiple addresses?

From what I've found, I should be able to accomplish this with a "push" via the shell. But I don't see "push" as method on the BasicDBObject.


回答1:


Your logic can be much simpler, as it turns out. You don't need to fetch customer by "email" (I'm assuming that this is your unique identifying key for Customer) just update.

findCustomer.put("email", custEmail); // search query for the customer email

// construct your newAddress object the same way you already are

BasicDBObject custMod = new BasicDBObject();
custMod.put("$addToSet", newAddress);
customerCollection.update(findCustomer, custMod, true /* upsert */, false /* multi */ );

Big problem with the way you have your logic now is it won't work multi-threaded. You can check for customer, and it won't be there. While you are constructing the object to insert it, another thread is already doing it. Since address object is an array rather than a single field, using $addToSet will add to the array if it exists, but if it's creating a new customer, then it will create address as an array.




回答2:


You want address to be a list of addresses instead of a single address document. So for new customers you want to have:

newCustomer.put("addresses", [newAddress])
customerCollection.save(newCustomer)

And for existing customers you want

customerCollection.update(newCustomer, {$push: {"addresses": newAddress}})

sorry, I don't know the java API, so you'll have to adapt the code above to create the appropriate objects



来源:https://stackoverflow.com/questions/10471553/add-multiple-sub-documents-in-mongodb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!