【问题标题】:Adding md5 hash value to mongo collection将 md5 哈希值添加到 mongo 集合
【发布时间】:2016-03-16 21:30:10
【问题描述】:

问题:我目前有一个包含 100,000 个文档的 mongo 集合。每个文档有 3 个字段(_id、姓名、年龄)。我想向每个名为 hashValue 的文档添加第 4 个字段,该字段存储每个文档名称字段的 md5 哈希值。

我目前可以通过 mongo shell 或通过 Mongoose ODM 作为 nodeJS 应用程序的一部分与我的集合进行交互。

可能的解决方案:

  1. 使用 Mongoose/nodeJs:

我意识到这行不通(不要相信您可以以这种方式遍历光标),但希望它显示了我正在尝试做的事情。

var crypto = require('crypto');

    MyCollection.find().forEach(function(el){
        var hash = crypto.createHash('md5').update(el.name).digest("hex");
        el.name = hash;
        el.save()
    });
  1. 使用 mongo Shell - 与上面几乎相同,我意识到类似上述语法的东西可以工作。唯一的问题是我不知道如何在 mongo shell 中创建 md5 哈希。但我能够遍历每个文档并添加一个字段。

  2. (可能的解决方法)- 这样做的目的是能够根据名称值的 md5 散列进行查询。我相信 mongo 允许您创建一个散列索引 (link here)。唯一的问题是我找不到任何人使用它进行查询的示例(似乎仅用于分片),我不确定这是否会在以后起作用。 (示例:我想对我从用户那里收集的名称进行 md5 哈希处理,然后查询我的 mongo 集合以查看是否可以在 hashValue 字段中找到该 md5 哈希)

【问题讨论】:

    标签: node.js mongodb hash mongoose md5


    【解决方案1】:

    Javascript 已经有称为 hex_md5 的 md5 哈希函数。它也可以在 mongo 控制台中使用。

    > hex_md5('john')
    527bd5b5d689e2c32ae974c6229ff785
    

    因此,要更新您的记录,您可以在 mongo 控制台中使用以下代码 sn-p:

    db.collection.find().forEach( function(data){
      data.hashValue = hex_md5(data.name);
      db.collection.save(data);
    });
    

    【讨论】:

    • 这非常适用于 mongo 控制台中的更新。如果需要在 mongoose 中进行更新,请参阅下面的答案。
    【解决方案2】:

    您可以使用streams 遍历mongoose 中的游标,并使用bulk 更新所有记录。

    mongoose.connection.on("open", function(err,conn) {
        var bulk = MyCollection.collection.initializeUnorderedBulkOp();
        MyCollection.find().stream()
            .on('data', function(el){
                var hash = crypto.createHash('md5').update(el.name).digest("hex");
                // add document update operation to a bulk
                bulk.find({'_id': el._id}).update({$set: {name: hash}});
            })
            .on('error', function(err){
                // handle error
            })
            .on('end', function(){
                // execute all bulk operations
                bulk.execute(function (error) {
                    // final callback
                    callback();                   
                });
            });
        });
    

    【讨论】:

    • 我阅读了文档,这似乎是在正确的轨道上。 bulk.find({'_id': el._id}).update({$set: {name: hash}});返回错误“TypeError:无法读取未定义的属性 'find'”。但总的来说,这条路径是一个很好的文档化解决方案。
    • 修复了该错误。我们需要先建立连接。
    【解决方案3】:

    我个人不喜欢使用选项 3(即可能的解决方法)。两个原因—— 1. 在查询数据时,我们必须确保应用程序使用相同的哈希函数,并以与 Mongo DB 相同的方式推导出哈希值。我认为 Mongo DB 使用 MD5 并且只考虑前 64 位哈希。我看到的缺点是应用程序与 Mongo DB 哈希的内部实现相关联,并且可能随时更改。

    1. 散列索引适用于点查询(等式查询)。但它们不支持范围查询(age > & age > 50)、like 或 regex 查询(db.users.find({"name": /ABC/})。

    不清楚的一点是,为什么要存储 name 列的 MD5 而不是在 name 列本身上创建普通索引。可能这将有助于得出答案。

    【讨论】:

    • 很好的问题并同意选项 3。原因是我试图找到一种在名称字段上进行有效文本搜索的方法。而且由于名称字段可以包含名称的多个部分(名字、中间名、姓氏),大多数解决方案需要多次查询、集合数据结构的更改或低效的正则表达式查询。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 2011-07-28
    • 1970-01-01
    • 2019-12-20
    • 1970-01-01
    相关资源
    最近更新 更多