Mongo在Meteor应用程序的_id_字段上给出重复键错误

时间:2015-03-10 10:28:15

标签: mongodb meteor

我正在搜索很长时间和很多关于这个问题的话题。到现在为止,我找不到任何解决方案。而且,对我来说并不是很清楚,希望你能提供帮助。这是我的问题:

我设计了一个Meteor应用程序,Mongo DB中有一个带有订单的集合。通过读取csv文件来填充该集合

import_file_orders = function(file) {
var lines = file.split('%\r\n');
var l = lines.length - 1;
for (var i=0; i < l; i++) {
  var line = lines[i];
  var line_parts = line.split('|');
  var ex_key = line_parts[0];
  var ex_name = line_parts[1];
  var clin_info = line_parts[2];
  var order_info = line_parts[3];
  var clinician_last_name = line_parts[4];
  var clinician_first_name = line_parts[5];
  var clinician_code = line_parts[6];
  var clinician_riziv = line_parts[7]
  var pat_id = line_parts[8];
  Meteor.orders.insert({Patient:pat_id, Exam_code:ex_key, Exam_name:ex_name, Clinical_info:clin_info, Order_info:order_info, Clinician:{first:clinician_first_name, last:clinician_last_name, c_code:clinician_code, riziv:clinician_riziv}, Planned:null});
  console.log("%");
};
}

阅读CSV文件后,集合中的某些文档会出错:

duplicate key error index: protocolplanner.Orders.$_id_ dup key: { :     "2ZGvRfuD8iMvRiXJd" } insert failed

当我运行Mongo命令db.Orders.getIndexes()时,我发现有两个索引:

{
  "v" : 1,
  "key" : {
           "_id" : 1
   },
   "name" : "_id_",
   "ns" : "protocolplanner.Orders"
 }

似乎有两个索引:一个_id索引(始终存在且无法删除)和一个_ id _索引。似乎_ id _索引导致错误。所以我有三个问题:

首先:为什么有一个_ id _索引?我在Meteor代码中没有定义索引。 第二:为什么该索引存在重复密钥错误? 第三:似乎我无法删除_ id _索引。为什么?我现在你不能删除_id索引,但在我看来这不是一个_id索引。

你可以看到我完全迷失了。请帮忙!

编辑:

如下所述,更多信息:

我正在阅读的数据量为10151行。在定义的客户端读取文件的函数。通过允许和拒绝规则,只有管理员用户可以将数据输入到mongo中。线条被正确读取。阅读文件后,应用程序中的所有数据都可用。几秒钟后,Mongo会自动创建索引并显示错误。从那时起,在应用程序中不再显示发生错误的行。

我在Mongo shell中尝试了以下内容:     db.Orders.find({_ ID: “2ZGvRfuD8iMvRiXJd”})

Mongo给了我正确的文件。这证明了_id确实是由数据插入数据库时​​由Meteor创建的。但是这个_id应该是唯一的,所以我对我的错误完全感到困惑。

编辑2: 经过一些试验和错误后,我有一些关于这个问题的新信息。也许这很有趣,所以我们可以找到这个问题的答案。

如上所述,当我在客户端读取数据时,即使我使用ObjecID而不是Meteor ID,我也会出现重复键错误。但是,当我通过mongoinsert命令将数据直接推送到Mongo时,所有数据都被很好地导入,并且不会发生错误。当我插入这么多数据时,似乎服务器和客户端之间存在冲突(可能是异步时序问题)。

此时我正在寻找一个解决方案来读取数据服务器端,希望不会发生错误。

2 个答案:

答案 0 :(得分:2)

这不会解决您的问题,但它应该指向正确的方向,并且可能使您能够找出可用于创建新问题的问题:

  

第一:为什么会有_id_索引?

没有。只有一个索引,它有一个名称和一个密钥描述符。这不是一回事。默认索引的名称_id_,其密钥为_id

  

为什么该索引存在重复密钥错误?

_id通常是在客户端创建的,而不是在服务器端创建的。问题是这些密钥来自哪里,因为2ZGvRfuD8iMvRiXJd肯定不是ObjectId。这可能是一个流星键,或者您使用了一些自定义主键,但我不知道如何生成这些键。也许产生密钥的任何东西容易发生碰撞?

有关这方面的更多信息会有所帮助,但我建议填写一个新问题,这样问题就不会变得太大或者会有很多历史。

  

第三:似乎我无法删除_ id _ index。为什么?

这是第一个答案的引理:您无法删除强制主键索引。

编辑:

默认情况下,

Meteor generates ids in a different way than MongoDb。这是有道理的,因为the convention for ObjectId makes collisions probable if the number of clients is large(即如果客户端不是服务器实例,而是客户端浏览器,其中可能有2-3个数量级)。

相反,Meteor显然使用了method to consistently generate pseudo-random numbers on client and server。令人生畏的是,该实现使用了PRNG和falls back to a not crypto-strong deterministic random number generator (Alea)。换句话说,了解如何完全生成你的id可能会很棘手,因为它取决于你环境的很多细节。

解决方法: 尝试使用ObjectId作为主键:

Orders= new Meteor.Collection('Orders', {idGeneration: 'MONGO'});

答案 1 :(得分:0)

到目前为止,还不清楚为什么存在重复键错误的问题。但是我尝试了一些东西,我发现了一个可行的解决方案。

我将数据的插入从客户端移动到服务器端。因此,我遵循了本主题中的解决方案:

How to import data from CSV file into Meteor collection at server side

当插入功能是服务器端时,不会出现重复键错误,并且一切正常。