Обновление документов

Последнее обновление: 30.10.2015

Обновление всего документа

Как и в консоли MongoDB в PHP для обновления документов определена функция update. Она принимает, как минимум, два параметра: критерий отбора документов, которые надо обновить, и новый документ, на который заменяются старые документы в выборке. Также можно определить третий необязательный параметр options, в котором можно установить семь свойств:

  • upsert: хранит булевое значение. Если равно true, и документов для обновления не найдено, то создается новый документ.

  • multiple: хранит булевое значение. Если равно true, то обновляются все найденные документы.

  • fsync: принимает булевое значение. По умолчанию равно false. Если значение равно true, то перед подтверждением удачного добавления данных в бд, они в обязательном порядке записываются на жесткий диск.

  • w: если равно 1, то можно проводить операции записи-удаления-обновления. Если равно 0, то подобные операции запрещены. По умолчанию равно 1

  • j: принимает булевое значение. По умолчанию равно false. Если значение равно true, то перед подтверждением удачного добавления данных в бд, они в обязательном порядке журналируются

  • wtimeout: указывает время в миллисекундах, которое сервер будет ожидать подтверждения обновления. По умолчанию равно 10000 миллисекунд

  • timeout: указывает время в миллисекундах, которое клиент будет ожидать ответ от базы данных

Итак, обновим документ:

$con = new MongoClient();
$collection= $con-> test-> persons;

// критерий отбора документов, которые надо обновить
$oldDocs=array("name"=> "Mark", "age" => 23);
// новый документ
$newDoc = array(	
	"name" => "Mark", 
	"age" =>  29, 
	"languages" =>   array("engish", "greek"), 
	"company" =>  array(
		"name" => "Facebook",
		"year" => 2004
	)
);
// дополнительные параметры обновления
// если документы по критерию не найдены, то новый документ вставляется
$option = array("upsert" => true);

$collection ->  update($oldDocs, $newDoc, $option);

// проверяем замену
$list = $collection->find();

while($document = $list-<getNext())
{
	print_r($document);
}
 $con->close();

В данном случае мы находим все документы, где ключ "name" имеет значение "Mark, а ключ "age" - значение 23. И затем заменяем элемент выборки на новый документ, передаваемый во втором параметре функции update.

Оператор $setOnInsert

Как мы увидели, если опция upsert равна true, то при отсутствии документа для обновления в коллекцию добавляется новый документ. Этот тот случай, когда мы можем задействовать оператор $setOnInsert. Данный оператор служит для установки значения какого-либо поля. Например:

$con = new MongoClient();
$collection= $con-> test-> persons;

// критерий отбора документов, которые надо обновить
$oldDocs=array("name"=> "Mark", "age" => 23);

$newDoc = array("$setInInsert" => array ("company" => array( 
	"name" => "Facebook",
	"year" => 2004
)));

$option = array("upsert" => true);

$collection ->  update($oldDocs, $newDoc, $option);

// проверяем замену
$list = $collection->find();

while($document = $list-<getNext())
{
	print_r($document);
}
 $con->close();

В итоге если функция update не найдет элемента для обновления, то в бд будет добавлен новый документ, для которого оператор $setOnInsert установит значение для ключа company.

Обновление поля документа

Очень утомительно обновлять весь документ, если нам надо обновить все одно значение. Поэтому в этом случае лучше воспользоваться оператором $set:

$con = new MongoClient();
$collection= $con-> test-> persons;

$oldDocs=array("name"=> "Mark", "age" => 29);
// новое значение для поля age
$newDoc = array ('$set' => array("age" =>  30));

$option = array("upsert" => true);

$collection ->  update($oldDocs, $newDoc, $option);

// проверяем замену
$list = $collection->find();

while($document = $list-<getNext())
{
	print_r($document);
}
 $con->close();

Так как в примере выше увеличивалось числовое значение поля age на единицу, то мы могли бы применить и другой оператор - $inc. Этот оператор увеличивает числовое значение на определенное количество. Применим вместо $set оператор $inc:

$con = new MongoClient();
$collection= $con-> test-> persons;

$oldDocs=array("name"=> "Mark", "age" => 30);
// новое значение для поля age
$newDoc = array ('$inc' => array("age" =>  5));

$option = array("upsert" => true);

$collection ->  update($oldDocs, $newDoc, $option);

// проверяем замену
$list = $collection->find();

while($document = $list-<getNext())
{
	print_r($document);
}
 $con->close();

Выражение array ('$inc' => array("age" => 5)); увеличит значение age на 5 единиц.

Удаление поля

Если оператор $set устанавливает значение поля, то оператор $unset удаляет его:

$con = new MongoClient();
$collection= $con-> test-> persons;

$oldDocs=array("name"=> "Mark", "age" => 35);

$forDelete = array ('$inc' => array("age" => 1));

$collection ->  update($oldDocs, $forDelete);

Переименование поля

Иногда требуется не изменить значение, а изменить ключ - переименовать поле. Для этого служит оператор $rename:

$con = new MongoClient();
$collection= $con-> test-> persons;

$oldDocs=array("name"=> "Mark", "age" => 35);

$forRename = array ('$rename' => array("name" => "first name"));

$collection ->  update($oldDocs, $forRename);

В данном случае поле name переименовывается в first name для первого элемента выборки.

Работа с полями-массивами

Отдельно следует рассмотреть ряд операторов, которые нацелены на работу с полями-массивами. Например, для добавления в массив нового значения используется оператор $push. Такой элемент уже есть, то будет добавлен второй элемент с таким же значением. Однако если массив с таким ключом не определен в документе, то приложение выдаст ошибку. Итак, добавим в массив languages новый элемент:

$con = new MongoClient();
$collection= $con-> test-> persons;

$oldDoc=array("name"=> "Mark", "age" => 35);

$newElem = array ('$push' => array("languages" => "spanish"));

$collection ->  update($oldDoc, $newElem);

Здесь добавляется одно новое значение - spanish - в массив languages. Однако у нас может возникнуть задача добавить сразу несколько значений одним разом. В этом случае нам надо использовать в связке с оператором $push оператор $each:

$con = new MongoClient();
$collection= $con-> test-> persons;

$oldDoc=array("name"=> "Mark", "age" => 35);

$newElem = array ('$push' => array("languages" => array( '$each' => array("russian", "ukrainian"))));

$collection ->  update($oldDoc, $newElem);

$push замечательно добавляет новые данные, но опять же мы сталкиваемся с проблемой: если такое значение уже есть в массиве, то оператор $push добавит в массив его копию. Чтобы избежать дублирования элементов, стоит применять оператор $addToSet:

$con = new MongoClient();
$collection= $con-> test-> persons;

$oldDoc=array("name"=> "Mark", "age" => 35);

//добавление набора
$newElem = array ('$addToSet' => array("languages" => array( '$each' => array("russian", "chinese"))));

// добавление одиночного элемента
// $newElem = array ('$addToSet' => array("languages" => "italian"));

$collection ->  update($oldDoc, $newElem);

Удаление элемента из массива

Если для добавления в массив используется оператор $push, то для удаления из массива - оператор $pop. Данный оператор может удалять либо первый элемент (если получает в качестве параметра число -1), либо последний элемент (тогда в качестве параметра передаем число 1):

$con = new MongoClient();
$collection= $con-> test-> persons;

$oldDoc=array("name"=> "Mark", "age" => 35);

// удаляем первый элемент из массива languages
$popElem = array ('$pop' => array("languages" => -1));

$collection ->  update($oldDoc, $popElem);

Похожую функциональность предлагает оператор pull, только в отличие от $pop, он удаляет элемент со всеми повторами в массиве (например, мы могли добавить ранее дубликаты с помощью $push и теперь хотим их удалить). Например:

$con = new MongoClient();
$collection= $con-> test-> persons;

$oldDoc=array("name"=> "Mark", "age" => 35);

// удаляем все вхождения значения greek в массиве languages
$delElem = array ('$pull' => array("languages" => "greek"));

$collection ->  update($oldDoc, $delElem);

Если нам надо удалить не одно, а несколько значений сразу, то мы можем применить оператор $pullAll:

$con = new MongoClient();
$collection= $con-> test-> persons;

$oldDoc=array("name"=> "Mark", "age" => 35);

// удаляем все вхождения значения greek в массиве languages
$delElems = array ('$pullAll' => array("languages" => array("greek", "english")));

$collection ->  update($oldDoc, $delElems);

Функция save

Функция save служит для обновления/добавления элемента. Она принимает два параметра: ассоциативный массив значений, которые надо обновить, и объект options, задающий дополнительные опции для сохранения документа. Этот объект options может принимать следующие параметры:

  • fsync: принимает булевое значение. По умолчанию равно false. Если значение равно true, то перед подтверждением удачного добавления данных в бд, они в обязательном порядке записываются на жесткий диск.

  • w: если равно 1, то можно проводить операции записи-удаления-обновления. Если равно 0, то подобные операции запрещены. По умолчанию равно 1

  • j: принимает булевое значение. По умолчанию равно false. Если значение равно true, то перед подтверждением удачного добавления данных в бд, они в обязательном порядке журналируются

  • wtimeout: указывает время в миллисекундах, которое сервер будет ожидать подтверждения обновления. По умолчанию равно 10000 миллисекунд

  • timeout: указывает время в миллисекундах, которое клиент будет ожидать ответ от базы данных

Используем функцию save для добавления и обновления документа:

// создаем новый документ
$newDoc = array(	
	"name" => "Mark", 
	"age" =>  29, 
	"languages" =>   array("engish", "greek"), 
	"company" =>  array(
		"name" => "Facebook",
		"year" => 2004
	)
);
// дополнительные параметры для добавления
$options = array("fsync" => true);

$con = new MongoClient();
$collection= $con-> test-> persons;

// сохраняем документ
$collection ->  save($newDoc, $options);

// документ сохранен, теперь изменим его свойство и обновим
$newDoc["age"]=30;
$collection ->  save($newDoc, $options);

Функция findAndModify

Драйвер php для mongodb также предоставляет еще одну функцию с возможностью обновления - функцию findAndModify. Эта функция обновляет один документ и возвращает результат в случае успешного обновления.

Эта функция может принимать четыре параметра:

  • query: определяет фильтр выборки. Если данный параметр не указан, то выборка включает все элементы коллекции, однако при этом будет обновляться всегда первый элемент выборки

  • update: определяет информацию, которая будет обновляться

  • fields: определяет поля документа, которые необходимо возвратить в качестве результата. И вне зависимости от указанных полей всегда будет возвращаться как минимум одно поле - _id

  • options: определяет дополнительные опции для обновления

    • sort: сортирует выборку в определенном порядке

    • remove: удаляет документ, если равно true

    • update: обновляет документ, если равно true

    • new: если равно true возвращает в качестве результата обновленный документ. Если равно false (как по умолчанию), то возвращает выбранный для обновления документ до его обновления

    • upsert: если равно true то выполняет вставку документа в коллекцию, если выборка не нашла ни одного документа для обновления

Посмотрим на примере:

// новый документ, на который будет обновляться старый
$newDoc = array(	
	"name" => "Pavel", 
	"age" =>  30, 
	"languages" => array("engish"), 
	"company" =>  array(
		"name" => "Vkontakte",
		"year" => 2007
	)
);
// фильтр для выборки документов
$oldDocs = array("name" => "Mark");

$con = new MongoClient();
$collection= $con-> test-> persons;

// получаем ранее обновленный документ
$updatedDocument = $collection -> findAndModify($oldDocs, $newDoc);

// получаем значение поля name в ранее обновленном документе - Mark
echo "<p>Предыдущее имя: " . $updatedDocument["name"] . "</p>"

Как вы видите, в данном контексте функция findAndModify эквивалентна простой функции update. Здесь также используются два параметра. Но при этом мы также получаем документ в его состоянии до обновления со всеми его полями. Теперь же используем дополнительные параметры:

// обновим значение одного свойства
$forUpdate = array('$set'=>("name" => "Pavel"));
// фильтр для выборки документов
$oldDocs = array("name" => "Mark");
// дополнительные опции для обновлени
$options = array ('new' => true);

$con = new MongoClient();
$collection= $con-> test-> persons;

// получаем ранее обновленный документ
$updatedDocument = $collection -> findAndModify($oldDocs, $forUpdate, null, $options);

print_r($updatedDocument);

Также как и в случае с функцией update, здесь мы можем применять различные операторы, например, $set для установки одного поля. В качестве дополнительного параметра $options = array ('new' => true) указываем, что мы хотим возвратить именно обновленный документ, а не который был до обновления. И поскольку параметр $fields мы не указываем, то его место в функции findAndModify занимает null.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850