Node.js / MongoDB / Mongoose:缓冲区比较

首先,有一点背景:

我试图检查一下图像的二进制数据是否已经保存在Mongo中。 鉴于以下模式:

var mongoose = require('mongoose') , Schema = mongoose.Schema; var imageSchema = new Schema({ mime: String, bin: { type: Buffer, index: { unique: true }}, uses : [{type: Schema.Types.ObjectId}] }); module.exports = mongoose.model('Image', imageSchema); 

…我想查询是否存在一个图像,如果它添加一个引用,我的对象正在使用它,然后更新它。 如果没有,我想创build(upsert)它。

鉴于它不存在的情况下,下面的代码完美的作品。 如果是这样,下面的代码不会,并将另一个图像文件添加到Mongo。 我觉得这可能是一个比较问题的Mongo缓冲区types与节点缓冲区,但我不知道如何正确地比较它们。 请让我知道如何更新下面! 谢谢!

 Image.findOneAndUpdate({ mime : contentType, bin : image }, { $pushAll : { uses : [ myObject._id ] } }, { upsert : true }, function(err, image) { if (err) console.log(err); // !!!image is created always, never updated!!! }); 

Mongoose将缓冲区元素注定要存储到mongodb 二进制 ,但它执行查询时适当的强制转换。 期望的行为也在unit testing中检查 (也存储和检索一个node.js缓冲区)。

你确定你传递了一个node.js缓冲区吗?

在任何情况下,我认为最好的办法来处理最初的问题(检查图像是否已经在数据库中)将存储二进制数据的强大的哈希摘要(sha1,sha256,…),并检查(使用encryption模块)。 在查询时,作为初步testing,您还可以检查二进制长度以避免不必要的计算。

有关如何在存储/查询图像之前获取图像摘要的示例:

 var crypto = require('crypto'); ... // be sure image is a node.js Buffer var image_digest = crypto.createHash('sha256'); image_digest.update(image); image_digest = image_digest.digest('base64'); 

通过包含图像数据的node.js Buffer来查询图像不是一个好主意。 你说得对,这可能是BSON二进制数据types和一个节点Buffer之间的问题,但是你的应用程序真的需要这样一个比较吗?

相反,我会添加一个imageID或slug字段到您的模式,添加一个索引到这个字段,并查询它,而不是你的findOneAndUpdate调用bin

 var imageSchema = new Schema({ imageID: { type: String, index: { unique: true }}, mime: String, bin: Buffer, uses : [{type: Schema.Types.ObjectId}] }); 

散列确实工作,我用过的另一个filter是图像的exif数据。 由于这是结构化的信息,如果你有一个exif数据匹配,你可以去下一步检查散列或文件大小匹配…

节点模块堆获取exif数据很好,很容易为您的存储:)示例代码获取节点的exif数据