我正在尝试更新文档的子文档,如下面的代码行
$bulkbatch = new MongoDB\Driver\BulkWrite(['ordered' => true]);
$subDocumentStatus = array(
"Status" => array(
"CurrentStatus" => $this->EmployeeStatus,
"StatusDate" => new MongoDB\BSON\UTCDateTime(strtotime($this->EmployeeStatusDate)*1000),
"IsActive" => $IsActive
)
);
$bulkbatch->update(
array(
'_id' => new MongoDB\BSON\ObjectID($this->id)
),
array(
'$addToSet' => $subDocumentStatus
),
[
'multi' => true,
'upsert' => false
]
);
$this->manager->executeBulkWrite($this->collection, $bulkbatch);
我有
这样的文件{
"EmployeeNumber": "123456",
"Instructor": NumberInt(1),
"Department": ObjectId("5a8173e6d2ccda13240015a4"),
"FirstName": "Faiza",
"MiddleName": "Yousuf",
"Status": [
{
"CurrentStatus": "Joined",
"StatusDate": ISODate("2018-02-28T23:00:00.0Z"),
"IsActive": NumberInt(1)
}
],
...
...
}
如果$ this-> EmployeeStatus包含"加入"和$ this-> EmployeeStatusDate包含一些不同的值,如上面包含的文档" 2019-05-28T23:00:00.0Z" (除了以前的值)然后它应该更新。
上面的代码插入了另一个子文档 像
这样的值 "Status": [
{
"CurrentStatus": "Joined",
"StatusDate": ISODate("2018-02-28T23:00:00.0Z"),
"IsActive": NumberInt(1)
},
{
"CurrentStatus": "Joined",
"StatusDate": ISODate("2019-05-28T23:00:00.0Z"),
"IsActive": NumberInt(1)
}
],
...
我希望在加入的情况下,应该更新现有的子文档。
请帮助!!!
答案 0 :(得分:1)
有两个Mongo呼叫的解决方案;首先尝试更新现有的子文档;如果没有修改子文档,则在主文档中插入一个。
这是一个单元测试,证明解决方案有效(主要功能是updateOrInsert
):
require_once __DIR__ . '/MongoTestHelper.php';
use MongoDB\BSON\ObjectID;
use MongoDB\BSON\UTCDateTime;
use tests\Dudulina\MongoTestHelper;
class TmpTest extends \PHPUnit_Framework_TestCase
{
/** @var \MongoDB\Collection */
private $collection;
/** @var ObjectID */
private $_id;
public function test_subdocumentExists()
{
$statusDate = new UTCDateTime(strtotime("2018-02-28T23:00:00.0Z"));
$employeeStatus = "Joined";
/**
* Test data
*/
$this->collection->insertOne([
"_id" => $this->_id,
"EmployeeNumber" => "123456",
"Instructor" => 1,
"Department" => new ObjectID("5a8173e6d2ccda13240015a4"),
"FirstName" => "Faiza",
"MiddleName" => "Yousuf",
"Status" => [
[
"CurrentStatus" => $employeeStatus,
"StatusDate" => $statusDate,
"IsActive" => 1,
],
],
]);
/**
* the real test
*/
$this->updateOrInsert($employeeStatus, $statusDate, 0);
/**
* we verify the execution
*/
$document = $this->collection->findOne([
"_id" => $this->_id,
]);
$this->assertCount(1, $document['Status']);
$this->assertSame(0, $document['Status'][0]['IsActive']);
}
public function test_subdocumentDoesNotExists()
{
$statusDate = new UTCDateTime(strtotime("2018-02-28T23:00:00.0Z"));
$employeeStatus = "Joined";
/**
* we insert some test data
*/
$this->collection->insertOne([
"_id" => $this->_id,
"EmployeeNumber" => "123456",
"Instructor" => 1,
"Department" => new ObjectID("5a8173e6d2ccda13240015a4"),
"FirstName" => "Faiza",
"MiddleName" => "Yousuf",
"Status" => [
[
"CurrentStatus" => 'SomeOtherStatus',
"StatusDate" => new UTCDateTime(strtotime("2010-02-28T23:00:00.0Z")),
"IsActive" => 1,
],
],
]);
/**
* the real test
*/
$this->updateOrInsert($employeeStatus, $statusDate, 0);
/**
* we verify the execution
*/
$document = $this->collection->findOne([
"_id" => $this->_id,
]);
/**
* now there are 2 subdocuments inserted
*/
$this->assertCount(2, $document['Status']);
/**
* we verify the second document
*/
$secondSubDocument = $document['Status'][1];
$this->assertSame(0, $secondSubDocument['IsActive']);
$this->assertSame('Joined', $secondSubDocument['CurrentStatus']);
$this->assertTrue($statusDate->toDateTime()->getTimestamp() === $secondSubDocument['StatusDate']->toDateTime()->getTimestamp());
}
/**
* The function that you should do
*/
private function updateOrInsert($employeeStatus, $statusDate, $isActive)
{
$updateResult = $this->collection->updateOne([
"_id" => $this->_id,
"Status.CurrentStatus" => $employeeStatus,
"StatusDate" => ['$ne' => $statusDate],
], [
'$set' => [
'Status.$.StatusDate' => $statusDate,
'Status.$.IsActive' => $isActive,
],
], [
'upsert' => false,
]);
if ($updateResult->getModifiedCount() === 0) {
$this->collection->updateOne([
"_id" => $this->_id,
], [
'$addToSet' => [
'Status' => [
"CurrentStatus" => $employeeStatus,
"StatusDate" => $statusDate,
"IsActive" => $isActive,
],
],
], [
'upsert' => false,
]);
}
}
protected function setUp()
{
$this->collection = (new MongoTestHelper())->selectCollection('eventStore');
$this->collection->deleteMany([]);
$this->_id = new ObjectID('47ecbc36e8fb4b50662adcf9');
}
}