我正在开发一个客户数据加载器,客户可以在其中拥有多个地址。如果找不到客户,我会创建它并添加地址。如果客户存在,我只需添加新地址,如下所示:
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);
这适用于新客户。问题是当客户已经存在时,新地址会覆盖现有地址。
如何将新地址添加到客户,以便保留多个地址?
从我发现的内容来看,我应该能够通过shell实现“推送”。但是我没有在BasicDBObject上看到“push”作为方法。
答案 0 :(得分:2)
您希望地址是地址列表而不是单个地址文档。因此,对于您希望拥有的新客户:
newCustomer.put("addresses", [newAddress]) customerCollection.save(newCustomer)
对于您想要的现有客户
customerCollection.update(newCustomer, {$push: {"addresses": newAddress}})
抱歉,我不知道java API,所以你必须调整上面的代码才能创建合适的对象
答案 1 :(得分:1)
事实证明,你的逻辑可以简单得多。您不需要通过“电子邮件”获取客户(我假设这是您对客户的唯一识别密钥)只需更新。
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 */ );
现在你的逻辑方式存在的一个大问题是它不能用于多线程。您可以检查客户,它不会在那里。在构造要插入它的对象时,另一个线程已经在做了。由于地址对象是一个数组而不是一个字段,因此使用$ addToSet将添加到数组(如果存在),但如果它正在创建一个新客户,那么它将创建一个数组地址。