Mongo 在 Meteor 应用程序中的 _id_ 字段上给出重复键错误
Posted
技术标签:
【中文标题】Mongo 在 Meteor 应用程序中的 _id_ 字段上给出重复键错误【英文标题】:Mongo gives duplicate key error on _id_ field in Meteor application 【发布时间】:2015-05-11 17:55:41 【问题描述】:我正在搜索很长时间和很多关于这个问题的主题。直到现在我找不到任何解决方案。此外,这对我来说并不完全清楚,希望您能提供帮助。这是我的问题:
我设计了一个 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 代码中没有定义任何索引。 第二:为什么该索引存在 dup key 错误? 第三:似乎我无法删除 _ id _ 索引。为什么?我现在您不能删除 _id 索引,但我认为这不是 _id 索引。
如你所见,我完全迷路了。请帮忙!
编辑:
如下评论,更多信息:
我正在读取的数据量是 10151 行。在定义的客户端读取文件的函数。通过允许和拒绝规则,只有管理员用户可以将数据输入 mongo。这些行被正确读取。读取文件后,应用程序中的所有数据都可用。几秒钟后,Mongo 会自动创建索引并出现错误。从那时起,发生错误的行在应用程序中不再可见。
我在 Mongo shell 中尝试了以下操作: db.Orders.find(_id:"2ZGvRfuD8iMvRiXJd")
Mongo 给了我正确的文件。这证明 _id 确实是 Meteor 在数据插入数据库时创建的。但是这个 _id 应该是唯一的,所以我对我遇到的错误完全感到困惑。
编辑 2: 经过一些试验和错误,我有一些关于这个问题的新信息。也许知道这很有趣,所以我们可以找到这个问题的答案。
如上所述,当我在客户端读取数据时,即使我使用 ObjecID 而不是 Meteor ID,也会出现重复键错误。但是,当我通过 mongoinsert 命令将数据直接推送到 Mongo 时,所有数据都导入良好,并且没有出现错误。当我插入这么多数据时,似乎服务器和客户端之间存在冲突(可能是异步计时问题)。
目前我正在寻找读取数据服务器端的解决方案,希望不会发生错误。
【问题讨论】:
好吧,请不要在这个空间里问“三个问题”,因为格式是“一个问题”,以便与接受的答案相协调。但是,对于 1 和 3,MongoDB 中的_id
字段是“主键”。它被认为是文档本身的“最终唯一标识符”。 MongoDB 本身对如何生成这个“独特”值有自己的概念。 Meteor 选择用它自己的定义来“替换”它。如果您的代码确实如图所示,那么“意图”是“主键”对于创建的每个文档都是唯一的。
好的,很抱歉这三个问题。但是,由于主键是唯一的,我不明白为什么会出现重复键错误。
如果这是客户端代码而不是在异步上下文中调用,你和我都会。考虑到主键的约束,这里的主要意图是“唯一值”。您也许可以编辑您的问题以包含有关您的操作是客户端还是服务器(猜测服务器)的更多信息。还有您正在处理的数据量。任何生成相同主键值的东西都令人担忧。但是,如果您可以添加更多信息来解释这一点,那将会很有帮助。
我正在读取的文件中的行数是 10151。当它们刚刚被读取时,应用程序中的每一行数据都是可用的。几秒钟后,控制台中出现错误(生成索引后)。之后在应用程序中看不到有错误的行。读取文件的函数在客户端定义。当我在 Mongo 控制台中使用查询中的 _id 字段进行搜索时(例如:db.Orders.find(_id:"2ZGvRfuD8iMvRiXJd")),然后我找到了正确的数据。这证明_id确实是Meteor在插入数据时创建的。通常它应该是唯一的
同意唯一的原则。将信息放在问题中比放在评论中更好。您的问题有一个编辑链接。使用它为您添加更多详细信息。
【参考方案1】:
这不会解决您的问题,但它应该为您指明正确的方向,并可能使您能够隔离可用于创建新问题的问题:
第一:为什么会有
_id_
索引?
没有。只有一个索引,它有一个名称和一个键描述符。那不是一回事。默认索引的name是_id_
,它的key是_id
。
为什么该索引存在 dup key 错误?
_id
通常是在客户端而不是服务器端创建的。问题是这些密钥从何而来,因为2ZGvRfuD8iMvRiXJd
肯定不是ObjectId
。这可能是一个流星键,或者您使用了一些自定义主键,但我不知道这些键是如何生成的。也许生成密钥的任何东西都容易发生冲突?
有关这方面的更多信息会有所帮助,但我建议提出一个新问题,这样问题就不会变得太大或获得太多历史记录。
第三:我似乎也无法删除 _ id _ 索引。为什么会这样?
这是第一个答案的引理:您不能删除强制主键索引。
编辑:
流星,默认情况下,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');
【讨论】:
对不起。这如何回答在稀释“为什么多个记录的主键相同”时解决的基本问题。当然内容扩展了我给自己的“评论”(在这个“答案”中提到)但是它回答了那个核心点吗?我不明白它是怎么做的。这真的只是一个很长的评论。 OP 很难隔离问题,这个答案回答了他总共提出的四个问题中的两个,并就如何隔离根本原因以创建一个更适合的新问题提供建议点。这并不总是与问答模式有关,还与帮助人们有关。我希望 OP 简化问题并发布一个新问题,而不是扩展当前问题,以更好地适应问答结构。 我想我说过,我想我说过你基本上反映了我在澄清中评论的内容,并用更长的版本来说明。这并没有“回答”“为什么会这样”的核心问题_id
值被插入”。如果您不知道答案,请发表评论。最好不要只是复制别人说过的话。
如您所见,我写的答案与您的第二条评论平行。你没有事件 attempt 来解释索引 key 和索引 name 不是一回事,所以我几乎没有复制你的评论。而是将精力集中在帮助他人上。
感谢您的回答。我在上面添加了一条评论,其中包含更多信息。但是目前我不知道出了什么问题。【参考方案2】:
目前还不清楚为什么会出现重复键错误的问题。不过我尝试了一些方法,找到了一个可行的解决方案。
我将数据的插入从客户端移动到服务器端。因此,我遵循了本主题中的解决方案:
How to import data from CSV file into Meteor collection at server side
当插入功能在服务器端时,不会出现重复键错误,并且一切正常。
【讨论】:
以上是关于Mongo 在 Meteor 应用程序中的 _id_ 字段上给出重复键错误的主要内容,如果未能解决你的问题,请参考以下文章
Meteor:你如何用 _id 字段将一个集合中的字段填充到另一个集合中?