Я бы предпочел использовать [:punct:]
для этого. Кроме того, a-zA-Z09-9
может быть просто [:alnum:]
:
[[ $TEST =~ ^[[:alnum:][:blank:][:punct:]]+$ ]]
В вопросе №1 разделим его на две части. Во-первых, увеличьте любой документ, который имеет «items.item_name», равный «my_item_two». Для этого вам придется использовать позиционный оператор «$». Что-то вроде:
db.bar.update( {user_id : 123456 , "items.item_name" : "my_item_two" } ,
{$inc : {"items.$.price" : 1} } ,
false ,
true);
Обратите внимание, что это только увеличит первый подобранный поддокумент в любом массиве (так что если у вас есть другой документ в массиве с «item_name», равным «my_item_two», он не будет получить прирост). Но это может быть то, что вы хотите.
Вторая часть сложнее. Мы можем вывести новый элемент в массив без «my_item_two» следующим образом:
db.bar.update( {user_id : 123456, "items.item_name" : {$ne : "my_item_two" }} ,
{$addToSet : {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } ,
false ,
true);
Для вашего вопроса №2 ответ проще. Чтобы увеличить общую сумму и цену item_three в любом документе, который содержит «my_item_three», вы можете одновременно использовать оператор $ inc на нескольких полях. Что-то вроде:
db.bar.update( {"items.item_name" : {$ne : "my_item_three" }} ,
{$inc : {total : 1 , "items.$.price" : 1}} ,
false ,
true);
Невозможно сделать это в одном запросе. Вы должны искать документ в первом запросе:
Если существует документ:
db.bar.update( {user_id : 123456 , "items.item_name" : "my_item_two" } ,
{$inc : {"items.$.price" : 1} } ,
false ,
true);
Else
db.bar.update( {user_id : 123456 } ,
{$addToSet : {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } ,
false ,
true);
Не нужно добавлять условие {$ne : "my_item_two" }
.
Также в многопоточной среде вы должны быть осторожны, чтобы только один поток мог выполнить второй (вставить регистр, если документ не был найден) за раз, в противном случае будут вставлены дублирующие вложенные документы.