2015-03-06 2 views
1

Я использую неизменяемые объекты с уникальным хешем. Мой клиент не знает, является ли объект базой данных или нет. Я хочу сделать вставку только в том случае, если объект еще не существует.in mongo можно вставить запись, только если ее еще нет

Я знаю, что могу запросить, а затем вставить, но это требует дополнительного кругового путешествия.

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

Я знаю, что могу усовершенствовать, но это связано с операциями базы данных, которые совершенно не нужны.

В sql Я бы использовал сервер хранимой процедуры на стороне сервера. Но я не совсем понимаю, как (если вообще) на стороне сервера javascript будет работать на это. Любые предложения?

+0

Что такое «операция с базой данных, которая совершенно не нужна?». Вы обращаетесь к серверу, и если он не существует, он создает его. Если ничего не нужно менять, запись не выполняется. Я думаю, что путаница здесь связана с устаревшим протоколом обновления с новым протоколом, используемым с Bulk updates, который вы должны использовать, где можете. См. [WriteResult] (http://docs.mongodb.org/manual/reference/method/WriteResult/) –

ответ

2

Я действительно думаю, что если вы посмотрите на Bulk Operations API как это реализовано с MongoDB 2.6 и выше, то вы должны увидеть, что обновления не проблема с коснувшись содержимого базы данных на всех.

Например, методы оболочки MongoDB теперь фактически используют API-интерфейс Bulk Operations под капотом. Это сразу видно из объекта WriteResult, возвращаемого в оболочку, но вы также можете проверить определение подписи метода, чтобы выявить это.

Основной тест:

db.uptest.update(
    { "data": "test" }, 
    { "$set": { "data": "test }}, 
    { "upsert": true } 
) 

WriteResult({ 
    "nMatched" : 0, 
    "nUpserted" : 1, 
    "nModified" : 0, 
    "_id" : ObjectId("54f97d8ee43b0048f69c5d88") 
}) 

Так что вставляли, теперь, когда вы выдаете снова:

db.uptest.update(
    { "data": "test" }, 
    { "$set": { "data": "test }}, 
    { "upsert": true } 
) 

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 }) 

ничего не сделал. Поскольку данные, которые были отправлены в обновлении, совпадают с данными, которые там находятся. У MongoDB есть умения, чтобы знать это сейчас и фактически не будет выполнять другие операции ввода-вывода, если это будет определено.

Помимо этого, я не уверен, что вы думаете, чего хотите достичь. Как бы вы «знали», что было в базе данных, не спрашивая об этом? Единственный способ добиться этого - это «кэшировать» данные каким-то образом в вашем приложении, а затем сначала запросить кеш, прежде чем делать заявление в базе данных. Это, вероятно, избыточно и в основном ненужно, учитывая, что вызовы должны быть довольно быстрыми в своем собственном праве.

Существует, конечно, всегда модификатор $setOnInsert для высокопараноидального или для использования в этой конкретной цели. Это абсолютно ничего не пишет, если операция не является «вставкой».

В более длинной форме с использованием API-интерфейс непосредственно вызов будет выглядеть следующим образом:

var bulk = db.uptest.initializeOrderBulkOperation(); 
bulk.find({ "data": "test"}) 
    .upsert() 
    .updateOne({ "$setOnInsert": { "data": "test" } }); 
bulk.execute(); 

Это довольно последовательно по всем реализациям языка в общем принципе.

MongoDB 2.6 существует уже некоторое время, и большинство поставщиков используют его в качестве стандартного развертывания. MongoDB 3.0 только что выпущен с момента написания.

Таким образом, новые протоколы записи должны быть тем, что вы используете. По умолчанию методы драйвера по умолчанию имеют значение по умолчанию, по крайней мере, выполняют те же «проверки версии сервера», как это реализовано в методах оболочки.

Так что даже для одиночных вызовов (и вы, вероятно, должны организовать массовые вызовы для чего-либо, кроме чистых обновлений «одного снимка»), это делает, поскольку для реализации вашей логики используется новый API. Также используйте, если необходимо, $setOnInsert.

+0

>> Кроме того, я не уверен, что вы думаете, чего хотите достичь. Как бы вы «знали», что было в базе данных, не спрашивая об этом? << Возможно, вы неправильно поняли. Мой клиент «не знает». –

+0

@TimPigden Это в основном то, что я сказал. Или это неправильная попытка указать мне, чтобы я отвечал иначе? В чем ваш смысл? –

+0

извините - не хотел оскорблять. Вы сказали, как я мог бы знать, не спрашивая. Я думал, что подразумевается, что я должен был знать, в то время как обратное было. –