我最近开始研究Mongo db。 这是我在数据库 homeconfig 和集合数据
中的mongo db中的示例文档{
"_id": {},
"user_id": "user",
"rooms": [
{
"name": "abhi",
"metadata": {
"user_id": "user",
"is_expired": "false",
"expired_on": null
}
}
],
"sections": [
{
"name": "section1",
"metadata": {
"user_id": "user",
"room": "abhi",
"is_expired": "false",
"expired_on": null
}
}
],
"devices": [
{
"id": "aur.01.Jpzp0o",
"metadata": {
"section_less": "true",
"label": "aa",
"is_active": null,
"is_loading": null,
"is_dimmable": null,
"type": "aura",
"sub_device": "aur.01",
"is_favourite": "false",
"dimming": null,
"energy_usage": 0,
"usage_today": 0,
"avg_usage": 0,
"ir_control": null,
"user_id": "user",
"room": "abhi",
"section": null,
"is_expired": "false",
"expired_on": null
}
}
]
}
上面显示的JSON只是我文档的一个示例。实际的那个很大,我无法透露原始副本。
以下是我用来更新文档中的集合的功能。
function removeSectionsFromMongo($user_id, $data, $date)
{
$collection = (new MongoConnect())->connect('homeconfig', 'data');
foreach ($data as $key ) {
$update = $collection->updateOne(['user_id'=>$user_id, 'sections' => ['$elemMatch' => ['name' => $key['name'], 'metadata.is_expired' => 'false' ]]],
['$set'=>['sections.$.metadata.is_expired'=>'true', 'sections.$.metadata.expired_on'=>$date]]
);
if($update->getModifiedCount() == 1)
{
echo "Section <".$key['name']."> removed from room <".$key['metadata']['room'].">."."\n";
}
}
}
变量$data
是一个如下所示的数组:
Array
(
[0] => Array
(
[name] => Appliances
[metadata] => Array
(
[user_id] => CubicalPrime
[room] => Dhruv
[is_expired] => false
[expired_on] =>
)
)
[1] => Array
(
[name] => Bathroom
[metadata] => Array
(
[user_id] => CubicalPrime
[room] => Dhruv
[is_expired] => false
[expired_on] =>
)
)
[2] => Array
(
[name] => Others
[metadata] => Array
(
[user_id] => CubicalPrime
[room] => Dhruv
[is_expired] => false
[expired_on] =>
)
)
)
当我执行该函数时,它应该更新我传递的数组sections
中匹配的文档中的所有$data
。
但是,它正在更新文件。但是当文档的大小增加时,有时sections
中的对象很少没有得到更新。即is_expired
字段未更新为true
&amp; <{1}}未通过日期更新。
当我再次运行相同的功能时,整个更新将在第二次发生。
仅在查询结果显示修改计数等于1时才回显。这意味着查询正在正确执行。但很少有文档没有得到更新。
expired_on
我试图弄清楚为什么文档第一次没有更新,但第二次更新!!
帮助我解决代码出了什么问题?
答案 0 :(得分:0)
您可以使用 bulkWrite()
API来利用您的更新,就像您在循环中发送异步更新的当前实现一样,这就是为什么您要更新某些文档而某些文档没有更新
bulkWrite()
API有一些方法可以允许您的更新操作在服务器上作为批处理执行,因此效率与每次迭代时不发送每个更新操作一样服务器,只有一次在500次操作中说。
以下演示了该方法:
function removeSectionsFromMongo($user_id, $data, $date) {
$bulkOps = array();
foreach ($data as $key ) {
$update = [
'updateOne' => [
[
'user_id' => $user_id,
'sections' => [
'$elemMatch' => [
'name' => $key['name'],
'metadata.is_expired' => 'false'
]
]
],
[
'$set' => [
'sections.$.metadata.is_expired' => 'true',
'sections.$.metadata.expired_on' => $date
]
]
]
];
array_push($bulkOps, $update);
}
$operation = new BulkWrite($databaseName, $collectionName, $bulkOps);
$result = $operation->execute($primaryServer);
echo $result->getModifiedCount();
}
答案 1 :(得分:0)
在对我的代码进行了大量挖掘之后,我又添加了一个条件来验证更新记录。
function removeSectionsFromMongo($user_id, $data, $date)
{
$collection = (new MongoConnect())->connect('homeconfig', 'data');
foreach ($data as $key ) {
$update = $collection->updateOne(['user_id'=>$user_id, 'sections' => ['$elemMatch' => ['name' => $key['name'], 'metadata.is_expired' => 'false', 'metadata.room' => $key['metadata']['room'] ]]],
['$set'=>['sections.$.metadata.is_expired'=>'true', 'sections.$.metadata.expired_on'=>$date]]
);
if($update->getModifiedCount() == 1)
{
echo "Section <".$key['name']."> removed from room <".$key['metadata']['room'].">."."\n";
}
}
}
请参阅上面的代码'metadata.room' => $key['metadata']['room']
中的内容。
现在记录正在照常更新。此外,我现在正在使用{strong> chridam 建议的bulkWrite()
来减少服务器上的负载。见下面的代码:
function removeSectionsFromMongo($user_id, $data, $date, $collection, $debug)
{
$bulkOps = array();
$sections = array(); $rooms = array();
foreach ($data as $key ) {
$update = [
'updateOne' => [
[
'user_id' => $user_id,
'sections' => [
'$elemMatch' => [
'name' => $key['name'],
'metadata.user_id' => $user_id,
'metadata.room' => $key['metadata']['room'],
'metadata.is_expired' => 'false'
]
]
],
[
'$set' => [
'sections.$.metadata.is_expired' => 'true',
'sections.$.metadata.expired_on' => $date
]
]
]
];
array_push($bulkOps, $update);
if($debug)
{
array_push($sections, $key['name']);
array_push($rooms, $key['metadata']['room']);
}
}
$result = $collection->bulkWrite($bulkOps);
if($result->getModifiedCount() == count($data))
{
if($debug)
{
for($i = 0; $i < count($sections); $i++)
{
echo "Section -".$sections[$i]."- removed from room -".$rooms[$i]."-."."\n";
}
}
return true;
}
return false;
}//end removeSectionsFromMongo()
我仍然无法理解为什么我以前的代码没有对记录进行一些验证。 这是Mongo Library中的错误还是别的什么!!
如果有人弄清楚是什么问题,请告诉我。