MongoDB 4.4,Java 驱动程序 4.2.3 - InsertManyResult.getInsertedIds() 不返回所有插入文档的 ID 问题详情JSON 结构示例代码我的问题

如何解决MongoDB 4.4,Java 驱动程序 4.2.3 - InsertManyResult.getInsertedIds() 不返回所有插入文档的 ID 问题详情JSON 结构示例代码我的问题

我试图在成功的 _id 操作后为插入的文档检索 InsertMany 的值。为此,我使用了 InsertManyResult.getInsertedIds()。虽然这种方法在大多数情况下都有效,但在某些情况下,并非所有 _id 值都被检索到。

我不确定我是否做错了什么,但我认为 InsertManyResult.getInsertedIds() 为插入的所有文档返回 _id

问题详情

我在 MongoDB 中插入 1000 个文档,分两批 500 个文档。每个文档的大小约为 1 MB。

使用 InsertMany 插入批次后,我尝试通过 _id 读取 InsertManyResult.getInsertedIds() 的值并将其保存到集合中以备后用。

我假设在通过 InsertMany 插入 500 文档后,InsertManyResult.getInsertedIds() 将返回 500 _id 值。然而,它只返回 16 _id 个值(500)。

当我直接通过 Mongo Shell 检查 Mongo 集合时,我看到所有记录都已成功插入。我的测试集合中有 1000 个文档。我只是无法通过 _id 获取所有插入文档的 InsertManyResult.getInsertedIds()。对于插入的 1000 个文档,我只得到 32 _id

JSON 结构

为了重现这个问题,我有 一个 JSON,它的大小约为 1 MB,如下所示。

{
  "textVal" : "RmKHtemmzJDXgEApmWeoZGrdZJZerIj1","intVal" : 161390623,"longVal" : "98213019054010317","timestampVal" : "2020-12-31 23:59:59.999","numericVal" : -401277306,"largeArrayVal" : [ "MMzJDXg","ApmWeoZGrdZJZerI","1LhTxQ","adprPSb1ZT",...,"QNLkBZuXenmYE77"]

}

请注意,键 largeArrayVal 包含几乎所有数据。为了可读性,我省略了大部分值。

示例代码

下面的代码将上面显示的 JSON 解析为 Document,然后通过 InsertMany 将其插入到 MongoDB。完成后,我尝试使用 _id 插入 InsertManyResult.getInsertedIds()

private static final int MAX_DOCUMENTS = 1000;
private static final int BULK_SIZE = 500;

private static List<ObjectId> insertBatchReturnIds(List<Document> insertBatch)
{
  List<ObjectId> insertedIds = new ArrayList<ObjectId>();
  InsertManyResult insertManyResult;

  insertManyResult = mongoClient.getDatabase(MONGO_DATABASE).getCollection(MONGO_COLLECTION).insertMany(insertBatch);
  insertManyResult.getInsertedIds().forEach((k,v) -> insertedIds.add(v.asObjectId().getValue()));

  System.out.println("Batch inseted:");
  System.out.println(" - Was ackNowladged: " + Boolean.toString(insertManyResult.wasAckNowledged()).toupperCase());
  System.out.println(" - InsertManyResult.getInsertedIds().size(): " + insertManyResult.getInsertedIds().size());

  return insertedIds;
}

private static void insertDocuments()
{
  int documentsInserted = 0;
  List<Document> insertBatch = new ArrayList<Document>();
  List<ObjectId> insertedIds = new ArrayList<ObjectId>();
  final String largeJson = loadLargeJsonFromFile("d:\\test-sample.json");

  System.out.println("Starting INSERT test...");
  while (documentsInserted < MAX_DOCUMENTS)
  {
    insertBatch.add(Document.parse(largeJson));
    documentsInserted++;

    if (documentsInserted % BULK_SIZE == 0)
    {
     insertedIds.addAll(insertBatchReturnIds(insertBatch));
     insertBatch.clear();
    }
  }
  if (insertBatch.size() > 0)
    insertedIds.addAll(insertBatchReturnIds(insertBatch));
  System.out.println("INSERT test finished");

  System.out.println(String.format("Expected IDs retrieved: %d. Actual IDs retrieved: %d.",MAX_DOCUMENTS,insertedIds.size()));
  if (insertedIds.size() != MAX_DOCUMENTS)
    throw new IllegalStateException("Not all _ID were returned for each document in batch");
}

示例输出

Starting INSERT test...
Batch inseted:
 - Was ackNowladged: TRUE
 - InsertManyResult.getInsertedIds().size(): 16
Batch inseted:
 - Was ackNowladged: TRUE
 - InsertManyResult.getInsertedIds().size(): 16
INSERT test finished
Expected IDs retrieved: 1000. Actual IDs retrieved: 32.
Exception in thread "main" java.lang.IllegalStateException: Not all _ID were returned for each document in batch

我的问题

  1. InsertManyResult.getInsertedIds() 是否意味着为插入的所有文档返回 _id
  2. 我使用 InsertManyResult.getInsertedIds() 的方式是否正确?
  3. 插入的 JSON 的大小可能是这里的一个因素吗?
  4. 我应该如何使用 InsertManyResult 获取插入文档的 _id

注意

我知道我可以在 _id 之后读取 Document.parse,因为它是生成它的驱动程序,或者我可以在插入文档后选择 _id
我想知道如何使用 InsertManyResult.getInsertedIds() 来实现这一点,因为它似乎是为了满足这一目的。

解决方法

您的文档有 1 mb 大,因此单个命令中最多只能包含 16 个文档。驱动程序确实会自动将整套文档拆分为批次,但您似乎是一次从一批读取 ID,因此问题可能是以下之一:

  • 存在一个驱动程序问题,即在将结果返回到您的应用程序之前它没有将批处理结果合并在一起
  • 驱动程序一次给您一批结果,因此您确实获得了所有 ID,但不在您期望的段中(在这种情况下,没有错误,但您确实需要处理批次,因为它们由司机提供)

Ruby 中的以下测试按预期工作,生成 100 个 ID:

c = Mongo::Client.new(['localhost:14920'])

docs = [{a: 'x'*1_000_000}]*100
res = c['foo'].insert_many(docs)

p res.inserted_ids.length
pp res.inserted_ids

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?