Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在MongoDB中添加多个子文档_Java_Mongodb_Mongodb Java - Fatal编程技术网

Java 在MongoDB中添加多个子文档

Java 在MongoDB中添加多个子文档,java,mongodb,mongodb-java,Java,Mongodb,Mongodb Java,我正在开发一个客户数据加载器,客户可以有多个地址。如果找不到客户,我将创建它并添加地址。如果客户存在,我只需添加新地址,如下所示: DBObject findCustomer = new BasicDBObject(); findCustomer.put("email", custEmail); //check for existing customer DBObject newCustomer = customerCollection.findOne(find

我正在开发一个客户数据加载器,客户可以有多个地址。如果找不到客户,我将创建它并添加地址。如果客户存在,我只需添加新地址,如下所示:

    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);
这适用于新客户。问题是,当客户已经存在时,新地址会覆盖现有地址

如何将新地址添加到客户,使其保留多个地址


根据我的发现,我应该能够通过外壳“推动”来完成这项工作。但我不认为“push”是BasicDBObject上的方法。

您希望address是一个地址列表,而不是一个地址文档。因此,对于您希望拥有的新客户:

newCustomer.put("addresses", [newAddress]) customerCollection.save(newCustomer) newCustomer.put(“地址”,[newAddress]) customerCollection.save(新客户) 对于您想要的现有客户

customerCollection.update(newCustomer, {$push: {"addresses": newAddress}}) update(newCustomer,{$push:{“地址”:newAddress})
抱歉,我不知道java API,因此您必须修改上面的代码以创建适当的对象

事实证明,您的逻辑可以简单得多。您不需要通过“电子邮件”获取客户(我假设这是您唯一的客户识别密钥),只需更新即可

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 */ );

您现在拥有逻辑的方式的一个大问题是它无法在多线程中工作。您可以检查客户,但它不会在那里。当您正在构造要插入的对象时,另一个线程已经在这样做了。由于address对象是一个数组而不是单个字段,如果存在,则使用$addToSet将添加到数组中,但如果它正在创建新客户,则会将address创建为一个数组。

谢谢@ChrisAtLee,我来试一试。$push对于现有客户是不正确的,除非您检查此地址记录是否不存在(即使您这样做,在多线程设置中也不安全。请改用$addToSet-它只会在不存在时添加,$push无条件添加)@AsyaKamsky您是否知道执行此操作的Java语法?是的。由于我认为此答案不正确,因此我将在单独的答案中发布它。这看起来很危险-当您有多个具有相同名字和姓氏的客户时会发生什么?如果两个线程试图创建相同的CU,则此代码也不是线程安全的有时,您可能会得到一个重复的地址。您也可能会两次推送相同的地址。Good points@AsyaKamsky,我将使用电子邮件地址作为搜索键。此外,这是一个单线程应用程序,用于将数据加载到MongoDB。如果有多个(竞争)线程是一种可能性,您建议如何考虑线程安全?有多种方法可以做到这一点-取决于您的应用程序逻辑的期望/需要。您可以使电子邮件唯一,然后第二次插入尝试将失败,但您的应用程序将需要期望并恢复。您可以使用Java并发,但如果问题是地址的多个副本,您可以使用$addToSet而不是$push,这样您就不会添加已经在列表中的地址。