C++ 修改Mongodb源代码,禁用自动生成单据的“\u id”字段

C++ 修改Mongodb源代码,禁用自动生成单据的“\u id”字段,c++,mongodb,C++,Mongodb,我想修改并编译现在mongodbas的最新源代码,mongodb版本v3.5.10-34-g27d21e6 from,以使插入文档时如果未提供_id字段,则不会自动生成。mongodb的当前官方版本要求存在此字段。我已在mongodb-win32-x86_64-v3.4上测试了此事实,最新版本为 我发现了一个相关的问题。但我认为我的问题与这一个问题并不相同,因为我的问题是要求修改源代码,而这一个是关于参数设置的,其答案对于当前版本的mongodb也不再可行 我知道官方的mongodb集团有他们的

我想修改并编译现在mongodbas的最新源代码,mongodb版本v3.5.10-34-g27d21e6 from,以使插入文档时如果未提供_id字段,则不会自动生成。mongodb的当前官方版本要求存在此字段。我已在mongodb-win32-x86_64-v3.4上测试了此事实,最新版本为

我发现了一个相关的问题。但我认为我的问题与这一个问题并不相同,因为我的问题是要求修改源代码,而这一个是关于参数设置的,其答案对于当前版本的mongodb也不再可行

我知道官方的mongodb集团有他们的理由和考虑需要这样一个id字段,因为他们已经决定引入这样一个要求,所以他们不太可能在不久的将来删除它。我也知道禁用_id会影响mongodb的一些功能,比如上面提到的复制。但我仍然想知道如何禁用它,因为我只将它用作一台机器上只运行一个实例的个人数据库。我确信我不需要其他功能。我认为存储是最重要的,所以我不希望此字段占用额外的磁盘空间。出于同样的原因,我需要具有压缩功能的wiredTiger引擎,因此我需要对相对较新版本的mongodb执行此操作

到目前为止,我已经使用安装了VS2015的SCON成功编译并链接了原始源代码v3.5.10-34-g27d21e6。所以我希望有人能告诉我应该修改哪些代码段/哪些源代码文件段/文件来禁用自动生成_id字段;哪些文件也需要进行修补,以检查_id的存在,如果找不到,即使他们真的不需要,也会拒绝正常工作

以下两个文件是我发现的似乎相关的文件:

1 mongo/src/mongo/db/ops/insert.cpp行:153-177

我试图按如下方式修改此文件,但之后_id仍然是自动创建的

发件人:

致:

2 mongo/src/mongo/bson/bsonobj.cpp线路:281-315

我没有修改这个文件,因为我没有看到哪行代码可以添加_id字段,只是觉得它可能与它在评论中提到的问题有关

/* note: addFields always adds _id even if not specified
   returns n added not counting _id unless requested.
*/
int BSONObj::addFields(BSONObj& from, set<string>& fields) {
    verify(isEmpty() && !isOwned()); /* partial implementation for now... */

    BSONObjBuilder b;

    int N = fields.size();
    int n = 0;
    BSONObjIterator i(from);
    bool gotId = false;
    while (i.moreWithEOO()) {
        BSONElement e = i.next();
        const char* fname = e.fieldName();
        if (fields.count(fname)) {
            b.append(e);
            ++n;
            gotId = gotId || strcmp(fname, "_id") == 0;
            if (n == N && gotId)
                break;
        } else if (strcmp(fname, "_id") == 0) {
            b.append(e);
            gotId = true;
            if (n == N && gotId)
                break;
        }
    }

    if (n) {
        *this = b.obj();
    }

    return n;
}
所以,这就是我现在所做的。
我不熟悉mongodb的源代码结构,它对我来说确实是一个巨大的项目。我期待着一份详细的待办事项清单,以便在不需要太多关于mongodb工作原理的知识的情况下修改代码。当然,任何其他类型的相关信息都是受欢迎的。提前感谢。

在您发布的第三个代码片段中,将bool gotId=false替换为bool gotId=true可能会使其按您的意愿运行,但也可能会破坏某些功能

您提到开始这项工作的原因是为了提高存储性能—删除一个字段真的会带来很大的不同吗?如果真是这样,我会很惊讶。更可能的是,您确实希望的某些功能可能不会在现在中断,可能会在您最不期望的时间点中断很长时间

除了警告,你说过你想要:

一个详细的待办事项列表,我可以按照它修改代码


您不太可能找到对MongoDB源代码足够熟悉的人,他们可以告诉您该源代码是否安全,以及如何在StackOverflow上删除此字段-您更可能通过尝试联系开发团队或至少是向源代码添加代码的人得到响应。不过,作为最后的警告,即使在那里,你也不太可能找到愿意花时间列出步骤的人。像这样的修改往往需要花费大量的时间来理解源代码-没有简单的解决方法。

您现在试图做的事情是行不通的_id本质上是主键,在代码中的许多地方都假设_id字段存在,当然是唯一的。如果您不太熟悉主键的概念,请将其视为数据库中唯一的记录标识。无标识==无记录

您寻求的具体利益是什么?你应该重新表述你的问题,并询问人们如何做到这一点

祝你好运

我刚刚尝试用bool gotId=true替换bool gotId=false,但没有成功,\u id仍然生成。我认为可以实现的存储性能取决于插入的文档的长度。如果每一个都很短,就像我的情况一样,对我来说仍然值得一试。我知道在StAcExobe上很难找到一个要做的列表,但是因为我想要的是蒙哥马多官员花时间考虑不支持的东西,我想这个问题更适合这里。但我还是会从开发团队中找人来帮助我。谢谢你的回答
根据您提到的相关问题,插入文档时可以覆盖默认的_id值。你破解服务器代码的目的是什么?这似乎是一条很长的路径,可能会节省一些字节,并且可能会导致细微的破坏,除非您进行彻底的测试。如果要进行更改,我建议使用稳定的分支v3.4,而不是开发分支v3.5/master。如果你喜欢WiredTiger,但不想得到分布式数据库或查询规划师的好处/开销,你也可以考虑使用直接的.@ Stennie空间节省:是的,对于每个文档,可能只保存几个字节。但在我的例子中,每个文档本身通常都很短,_id字段仍然占据不可忽略的容量比例,这将随着大量文档的添加而累积。由于这是个人使用的,我不能像公司那样只添加更多的磁盘,而且我的电脑上已经没有磁盘空间了。所以我只想通过压缩和删除不必要的字段来压缩磁盘空间,尽可能多。@Stennie关于困难:我不熟悉mongodb的源代码,我也不清楚这次黑客攻击的困难。我希望源代码的设计是如此的周密,以至于会有一些神奇的开关等着我去发现,它们可以很容易地做到这一点,只有我不熟悉的代码才能很容易地找到它们。我仍然希望是这样。@Stennie关于这个版本:是的,我同意,v3.4会更好,我会试试,谢谢你的提示。关于WiredTiger,我认为你的推荐对我很有吸引力,因为它最能满足我的要求。但考虑到学习如何使用WiredTiger库编程所需的难度和时间投入,我目前对WiredTiger库除了支持压缩和行级锁之外没有太多了解,我认为修补Mongodb的一些代码对我来说似乎更可取、更实用。但是我会让门开着的,谢谢你提供的信息。为什么不重命名一个已经使用_id的现有字段,然后在创建集合时确保_id上不存在唯一索引?_id在mongodb中默认是唯一的。当插入未指定_id的文档时,mongodb将自动创建类型为ObjectId的文档,并通过在_id上应用唯一索引来确保其唯一性。但是,如果在创建集合时指定了{autoIndexID:false},则不会在_id上创建唯一索引,因此不会执行重复检查;现在,如果插入了具有重复_id的文档,_id字段在集合中是非唯一的。autoIndexID自v3.2以来被称为不推荐使用,但截至我在v3.5.10-34-g27d21e6上的测试,它仍然有效。我寻求的是通过禁用自动生成_id字段及其相应索引来减少一些额外的存储。我知道有一些解决方法,比如在创建集合时将autoIndexID设置为false,以禁用索引,并为_id分配一个伪值(最小长度值),从而禁止系统自动生成长值。但我觉得结果集合中的_id的伪值并不优雅,我知道我永远不会使用这些伪值。另外,如果可以完全删除_id文件,我可以获得额外的存储减少。所以我想修改代码。为什么不把最小的id字段传递给他们呢?说null。@AsyaKamsky如果我最终无法找到修改源代码的正确方法,我想我会传递尽可能小的id作为解决方法。但我仍然希望代码可以修改为完全禁用_id字段,以保持数据库中存储的数据看起来更整洁。顺便说一句,正如您所建议的,null看起来是一个很好的候选者。那么,你有关于空值需要多少位的信息吗?谢谢
if (firstElementIsId) {
        //b.append(doc.firstElement());
        i.next();
    } else {
        BSONElement e = doc["_id"];
        if (e.type()) {
            //b.append(e);
        } else {
            //b.appendOID("_id", NULL, true);
        }
    }

    while (i.more()) {
        BSONElement e = i.next();
        if (hadId && e.fieldNameStringData() == "_id") {
            // no-op
        } else if (e.fieldNameStringData() == "_id") {
            // no-op
        } else if (e.type() == bsonTimestamp && e.timestampValue() == 0) {
            auto nextTime = LogicalClock::get(service)->reserveTicks(1);
            b.append(e.fieldName(), nextTime.asTimestamp());
        } else {
            b.append(e);
        }
    }
/* note: addFields always adds _id even if not specified
   returns n added not counting _id unless requested.
*/
int BSONObj::addFields(BSONObj& from, set<string>& fields) {
    verify(isEmpty() && !isOwned()); /* partial implementation for now... */

    BSONObjBuilder b;

    int N = fields.size();
    int n = 0;
    BSONObjIterator i(from);
    bool gotId = false;
    while (i.moreWithEOO()) {
        BSONElement e = i.next();
        const char* fname = e.fieldName();
        if (fields.count(fname)) {
            b.append(e);
            ++n;
            gotId = gotId || strcmp(fname, "_id") == 0;
            if (n == N && gotId)
                break;
        } else if (strcmp(fname, "_id") == 0) {
            b.append(e);
            gotId = true;
            if (n == N && gotId)
                break;
        }
    }

    if (n) {
        *this = b.obj();
    }

    return n;
}