2013-09-10 3 views
4

Во-первых, немного предыстории:Node.js/MongoDB/Mongoose: Buffer Сравнение

Я пытаюсь проверить, если двоичные данные изображение в уже сохранена в Монго. Учитывая следующую схему:

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); 

... Я хочу, чтобы запросить, чтобы увидеть, если изображение существует, если он добавляет ссылку, что мой объект использует его, а затем обновить его. Если это не так, я хочу создать (обновить) его.

Учитывая, что он не существует, приведенный ниже код работает отлично. Если это так, то нижеследующий код не делает и добавляет еще один документ изображения в Mongo. Я чувствую, что это, вероятно, проблема сравнения для типа Mongo Buffer vs node Buffer, но я не могу понять, как правильно их сравнивать. Пожалуйста, дайте мне знать, как обновить ниже! Благодаря!

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!!! 
}); 
+0

Когда вы добавили уникальный индекс? Я потратил годы, пытаясь понять, почему он допускает дубликаты, перезапуск монго и переиндексацию исправил проблему для меня после добавления уникального индекса. –

+0

У меня был уникальный индекс, установленный в схеме, подумал я с самого начала. Но возможно, я добавил его после создания первоначальной коллекции. – guydog28

ответ

6

Mongoose преобразует буферные элементы, предназначенные для хранения в mongodb Binary, но при выполнении запросов выполняет соответствующие приведения. Ожидаемое поведение также проверяется в units tests (а также на хранение и извлечение буфера node.js).

Вы уверены, что используете node.js Buffer?

В любом случае, я считаю, что лучший подход для обработки исходной проблемы (проверьте, если изображение уже находится в db) будет хранить сильный хэш-файл (sha1, sha256, ...) двоичных данных и проверять что (используя криптовый модуль). При запросе в качестве предварительного теста вы также можете проверить двоичную длину, чтобы избежать ненужных вычислений.

Для примера того, как получить дайджест для изображения перед хранением/запрашивая его:

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'); 
+0

Спасибо. Хэш работает хорошо, не могу поверить, что я об этом не думал. Мне нужно будет сделать некоторые тесты на основе тех модульных тестов, которые вы предоставили только для моего собственного назидания. Благодаря! – guydog28

0

Нежелательно запрашивать изображение с помощью буфера node.js, который содержит данные изображения. Вы правы, что это, вероятно, проблема между бинарным типом данных BSON и буфером узлов, но действительно ли ваше приложение требует такого сравнения?

Вместо этого, я бы добавить ImageID или поле пробкового к вашей схеме, добавить индекс к этой области, и запрос на него вместо bin в вашем findOneAndUpdate вызова:

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

Итак, если бы я хотел, чтобы одно и то же изображение не могло быть загружено дважды, даже под разными именами файлов, могу ли я использовать этот метод? – guydog28

+0

Если у вас действительно нет метаданных, которые вы могли бы использовать для уникальной идентификации изображений, вам нужно как-то сравнить фактические данные изображения. Но это будет работать, только если все изображения имеют одинаковый формат.Кроме того, для выполнения таких сравнений вам, вероятно, понадобится еще какой-то инструмент специального назначения (то есть не MongoDB), который понимает форматы изображений и, возможно, может делать сравнения без фактического сравнения всего байта изображения по байтам. –

+0

хеширование, вот что я искал. Ваш ответ по-прежнему действителен и полезен, поэтому +1, а другой - именно то, что мне нужно. Благодарю. – guydog28

0

хэша делает работу, другой фильтр я использовал это Копируется данные для изображения. Поскольку это структурированная информация, если у вас есть соответствие по данным exif, вы можете перейти к следующему этапу проверки соответствия по размеру хэша или файла ...

кучи узлов модулей, чтобы получить exif данные приятны и легко для вашего хранения :) Пример кода для получения данных exif для узла