Ruby 我如何知道实际插入了多少Mongo文档?

Ruby 我如何知道实际插入了多少Mongo文档?,ruby,mongodb,Ruby,Mongodb,我有一个函数如下所示: def insert_multiple_cakes(cake_list) ensure_indexes insert_list = cake_list.map { |cake| mongofy_values(cake.to_hash) } inserted = db[CAKE_COLLECTION].insert(insert_list, w: 0) return inserted.length end 该函数的目标是将蛋糕列表中的所有蛋糕插入Mo

我有一个函数如下所示:

def insert_multiple_cakes(cake_list)
  ensure_indexes

  insert_list = cake_list.map { |cake| mongofy_values(cake.to_hash) }

  inserted = db[CAKE_COLLECTION].insert(insert_list, w: 0)

  return inserted.length
end
该函数的目标是将
蛋糕列表
中的所有蛋糕插入Mongo数据库。应忽略数据库中已存在的任何蛋糕。函数应该返回插入的蛋糕数量,因此如果
cake\u list
包含5个蛋糕,并且其中2个蛋糕已经存在于数据库中,那么函数应该返回3个

我的问题是,经过一个小时的实验,我得出以下结论:

  • 如果写入关注点(
    :w
    选项)为0,则insert调用将自动忽略所有重复的插入,并且返回值包含所有输入文档,甚至包括未插入的文档。无论我设置了什么
    :continue\u on\u error
    :collect\u on\u error
    ,返回值始终包含所有文档,并且收集的错误列表始终为空

  • 如果写入问题为1,则如果输入文档中存在任何重复项,则insert调用将失败,并出现
    Mongo::OperationFailure
    。无论我将
    :continue_on_error
    :collect_on_error
    设置为什么,当存在重复项时,插入总是失败

因此,在我看来,实现这一点的唯一方法是迭代输入列表,对每个文档执行搜索,并过滤掉已经存在的文档。我的应用程序一次要处理(至少)数千个插入,所以我喜欢这个计划就像我想跳桥一样

我是否误解了什么,或者Ruby客户端可能被窃听了


为了演示,此函数正是我想要的,并且工作正常:

def insert_multiple_cakes(cake_list)
  ensure_indexes

  collection = db[CAKE_COLLECTION]

  # Filters away any cakes that already exists in the database.
  filtered_list = cake_list.reject { |cake|
    collection.count(query: {"name" => cake.name}) == 1
  }

  insert_list = filtered_list.map { |cake| mongofy_values(cake.to_hash) }

  inserted = collection.insert(insert_list)

  return inserted.length
end
问题是,它执行了大约数百万次搜索,而实际上它只需要执行一次插入



您可以这样做():

ex.result
包含插入的
n以及每个失败的原因

{"ok"=>1,
 "n"=>2,
 "code"=>65,
 "errmsg"=>"batch item errors occurred",
 "nInserted"=>2,
 "writeErrors"=>
  [{"index"=>1,
    "code"=>11000,
    "errmsg"=>
     "insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.cakes.$_id_  dup key: { : \"strawberry\" }"},
   {"index"=>3,
    "code"=>11000,
    "errmsg"=>
     "insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.cakes.$_id_  dup key: { : \"chocolate\" }"}]}

批量操作是一条出路。我接受ranman的回答,但我想我应该分享我的最终代码:

def insert_documents(collection_name, documents)
  collection = db[collection_name]

  bulk = collection.initialize_unordered_bulk_op
  inserts = 0

  documents.each { |doc|
    bulk.insert doc

    inserts += 1
  }

  begin
    bulk.execute
  rescue Mongo::BulkWriteError => e
    inserts = e.result["nInserted"]
  end

  return inserts
end

def insert_cakes(cakes)
  ensure_cake_indexes

  doc_list = cakes.map { |cake|
    mongofy_values(cake.to_hash)
  }

  return insert_documents(CAKE_COLLECTION, doc_list)
end

查看批量API:w:0的写入关注点与广告中的完全一样。没有给出结果。这是“开火并忘记”,所以您基本上是告诉服务器“不要告诉您”发生了什么。批量操作提供了更多信息,但不适用于
w:0
,因此@ranman在提供帮助方面是不正确的。只要你得到一个“确认知识”,你的代码就会工作。您以错误的方式使用服务以获得预期的结果。@NeilLunn:好的,那么我如何以正确的方式使用服务以获得预期的结果呢?他的问题不是写问题,而是知道他添加了多少新项目。在本例中,批量API是完美的。任何其他实际给出响应的响应
{w:1}
是一个基本的开始。通过请求
{w:0}
可以明确地请求服务器不响应。明白吗?“无序操作”基本上是这里的关键,因为它跳过错误并根据定义报告它们。但是您仍然可以在这里传递
{w:0}
写关注点,而不获取错误报告。这就是我的观点。但是+1是正确的方法。是的,更新了我的答案以反映这一点。另外,我完全理解writeconcern,我只是不明白你为什么要提出这个问题(尽管现在我知道)——我在mongodb工作了很多年:)。找到狂热的mongodb粉丝总是很棒。那么,当你用一系列文档运行
insert
时,会发生什么呢?Ruby Mongo驱动程序一次只做一次插入吗?@Hubro不,它实际上是以一种“传统”的方式“批量”提交所有内容。批量操作API是前进的方向,因为它提供了比传统API更好的响应。因此,是的,我们的“粉丝”(/contributors)确实希望批量API提供更好的响应。尽管如此,我们还是希望每个人都能理解Write concern的用法。
def insert_documents(collection_name, documents)
  collection = db[collection_name]

  bulk = collection.initialize_unordered_bulk_op
  inserts = 0

  documents.each { |doc|
    bulk.insert doc

    inserts += 1
  }

  begin
    bulk.execute
  rescue Mongo::BulkWriteError => e
    inserts = e.result["nInserted"]
  end

  return inserts
end

def insert_cakes(cakes)
  ensure_cake_indexes

  doc_list = cakes.map { |cake|
    mongofy_values(cake.to_hash)
  }

  return insert_documents(CAKE_COLLECTION, doc_list)
end