【问题标题】:MongoDB: "can't save partial objects" exceptionMongoDB:“无法保存部分对象”异常
【发布时间】:2013-06-14 15:03:22
【问题描述】:

我正在尝试使用 Java API 从一个集合中查询并插入另一个集合,但我遇到了一个我不理解的异常:

Exception in thread "main" java.lang.IllegalArgumentException: can't save partial objects
    at com.mongodb.DBCollection._checkObject(DBCollection.java:1380)
    at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:222)
    at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:205)
    at com.mongodb.DBCollection.insert(DBCollection.java:57)
    at com.mongodb.DBCollection.insert(DBCollection.java:100)

我需要在文档上调用一些“最终确定”方法吗?我的代码是这样的:

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

Mongo mongo = new Mongo("mongodb://...");
DB db = mongo.getDB("foo");
DBCollection rawCollection = db.getCollection("foo1");
DBCollection aggCollection = db.getCollection("foo2");

DateTimeZone tz = DateTimeZone.forOffsetHours(-5);

BasicDBObject toGrab = new BasicDBObject("Time1", 1).append("col2", 1).append("col3", 1);
DBCursor c = rawCollection.find(null, toGrab).limit(10);

for (DBObject doc : c) {
  Date newDate = new DateTime( ((BasicBSONObject) doc).getDate("Time1") )
                   .withZone(tz).monthOfYear().roundCeilingCopy()
                   .withZone(DateTimeZone.UTC).toDate();

  doc.put("Time2", newDate);

  aggCollection.insert(doc);
}

【问题讨论】:

    标签: java mongodb insert database


    【解决方案1】:

    您正在使用 collection.find(query,projection) 查询特定字段

    通过在 find 操作的参数中指定 projection,该集合将返回一个部分对象。

    从发布的堆栈跟踪来看,当调用“插入”时,底层 API 正在运行 _checkObject(doc),这会引发“部分对象”的异常,因为这与游标返回的实例相同。

    您可以通过创建 (new BasicDBObject(doc)) 有效地复制返回的部分对象,然后将副本保存到 aggCollection.. 来解决此问题。

    BasicDBObject doc = ...;
    BasicDBObject copyOfDoc = new BasicDBObject(doc);
    copyOfDoc.put("Time2", newDate);
    aggCollection.insert(copyOfDoc);
    

    参见Findcollection sourcemap constructor

    【讨论】:

    • 好像没有这样的方法new BasicDBObject(doc),有没有其他简单的方法来克隆文档?还是我必须逐个字段?
    • BasicDBObject 的构造函数接受一个映射,创建一个包含映射中所有属性的对象。 BasicDBObject 还实现了 Map 接口,因此您可以通过将源对象用作 Map 的实例来创建具有与 basicDBObject1 相同的所有属性的新 BasicDBObject(不是多态性吗?)。我将使用代码示例编辑答案。
    • 让我大吃一惊的是BasicDBObject 实现了Map,但查询返回DBObjects,它没有实现Map。所以我只需要投射。不是最漂亮的界面,但它应该可以工作,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-15
    • 1970-01-01
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    相关资源
    最近更新 更多