MongoDB update sub document issue - php

I'm having Mongo structure like this,
"campaigns":[{
"summary" :
[ {
"postcode" : [ {
"id" : "71",
"name" : "Recall 1",
"qty" : 3,
"history" :
[ { "timestamp" : "2014-12-16 11:15:32",
{ "timestamp": "2014-12-16 11:15:53"
} ]
} ]
},
{
"postcode" :
[ {
"id" : "72",
"name" : "Recall 2",
"qty" : 1,
"history" : [ { "timestamp" : "2014-12-16 11:15:53" } ]
} ]
}]
I'm trying to i) increment qty of postcode.id : 72 ii) insert another timestamp for that same postcode id 72.
My code:
$collection->update(array("campaigns.task.id" => $b,"_id"=> new MongoId($objectid),"campaigns.0.summary.0.postcode.0.id" => $a), array('$inc' => array('campaigns.0.summary.0.postcode.0.qty' => 1)));
$collection->update(array("campaigns.task.id" => $b,"_id"=>new MongoId($objectid),"campaigns.0.summary.0.postcode.0.id" => $a),
array('$addToSet' => array('campaigns.0.summary.0.postcode.0.history' => array("timestamp"=>$now->format('Y-m-d H:i:s')))));
but postcode.id = 72 not gets updated, i'm confused with this nested subdocument can anyone suggest me the solution ?

Related

yii2 mongodb update embedded array

How to update members age whose name is TEST1 using yii2.?
Used below code to update , but i am specifying the indexes there , i want with out specifying the indexes.
User::updateAll([ '$set'=> ['Addresses.0.members.0.age'=>100] ],['IN','Addresses.members.name',['TEST1'] ]);
{
"_id" : ObjectId("595209b65312f48195fb2e01"),
"username" : "Test name",
"Addresses" : [
{
"address_no" : 1,
"Address" : "Test house",
"City" : "test city",
"State" : "Test state",
"Mobile" : "9999999",
"members" : [
{
"name" : "TEST1",
"age" : 35
},
{
"name" : "TEST2",
"age" : 30
},
]
},
{
"address_no" : 2,
"Address" : "2B, Test place",
"City" : "Test city",
"State" : "Test State",
"Pincode" : "12345",
"Phone" : "1234568789",
"Mobile" : 9999999999
}
],
"Beneficiaries" : [
{
"beneficiary_id" : 1,
"Name" : "Test1",
"Age" : "28",
"Sex" : "F"
}
],
"auth_key" : "esd8d89ds89ds89ds89ds",
}
there is position operator $ to do this kind of job
{
"Addresses.members.name" : "TEST2",
},
{
$set: {
"Addresses.$.members.0.age" : 40
}
}
Here I specified first index as it supports up to one level depth.
New feature might release in future to resolve this issue: https://jira.mongodb.org/browse/SERVER-831
Yii::$app->mongodb->getCollection('user')->update(['_id' => $id, 'members.name' => 'Test1'], ['$set' => [
'members.$.age' => 100,
]]);

$pipeline is not a list (unexpected index: "$group") in Laravel

When the below query is run the results are displayed in mongo shell.
Sample Records
{
"_id" : ObjectId("587e21df6e79d255011a9c6a"),
"vendor_id" : "101",
"subscription_id" : 14,
"created_at" : ISODate("2017-01-17T13:53:35.272Z")
}
{
"_id" : ObjectId("587e21df6e79d255011a9c6c"),
"vendor_id" : "102",
"subscription_id" : 14,
"created_at" : ISODate("2017-01-17T13:56:35.272Z")
}
Query
db.user_config.aggregate({$group:
{
_id : "$subscription_id",
list:
{
$push:
{
_id: "$_id",
vendor_id: "$vendor_id"
}
}
}})
Results
/* 1 */
{
"result" : [
{
"_id" : 14,
"list" : [
{
"_id" : ObjectId("587e21df6e79d255011a9c6a"),
"vendor_id" : "user_101"
},
{
"_id" : ObjectId("587e21df6e79d255011a9c6b"),
"vendor_id" : "user_101"
}
]
}
],
"ok" : 1.0000000000000000
}
But when same thing is done through laravel the following error occurs. $pipeline is not a list (unexpected index: "$group")
Below is the laravel code
$configuration_list = UserConfig::raw()->aggregate([
'$group' => [
'_id' => '$subscription_id',
'list' => ['$push' =>
['_id' => '$_id', 'vendor_id' => '$vendor_id']]
]
]
);
Can someone please help me solve this issue..
Wrap the aggregation pipeline steps in an array:
$pipeline = [
[
'$group' => [
'_id' => '$subscription_id',
'list' => [
'$push' => [
'_id' => '$_id',
'vendor_id' => '$vendor_id'
]
]
]
]
];
$configuration_list = UserConfig::raw()->aggregate($pipeline);

creating json array from php array

I've following array in php
Array
(
[0] => Array
(
[team1_score] => 10
[team2_score] => 5
[round_number] => 1
[teamtitle1] => Chennai super kings
[teamtitle2] => Spartans
)
[1] => Array
(
[team1_score] => 15
[team2_score] => 10
[round_number] => 1
[teamtitle1] => Lions11
[teamtitle2] => Kings Xl Punjab
)
[2] => Array
(
[team1_score] => 15
[team2_score] => 5
[round_number] => 1
[teamtitle1] => Zimbabwe
[teamtitle2] => Red Steel
)
[3] => Array
(
[team1_score] => 10
[team2_score] => 15
[round_number] => 2
[teamtitle1] => Zimbabwe
[teamtitle2] => Chennai super kings
)
[4] => Array
(
[team1_score] =>
[team2_score] =>
[round_number] => 3
[teamtitle1] =>
[teamtitle2] =>
)
)
I want to generate tournament brackets from this array. I'd found jquery plugin for creating tournament brackets. For generating the tournament brackets I've to form json array round wise. for round 1 it should give me 3 records for round 2 1 records and for round 3 1 record. I've tried the following code :-
<script type="text/javascript">
(function (win, doc, $) {
win.TestData<?php echo $cnt; ?> = [
<?php
foreach ($roundmatcharr as $mt => $matchval) {
if (isset($matchval["teamtitle1"]) && $matchval["teamtitle1"] != "") {
$team1 = $matchval["teamtitle1"];
} else {
$team1 = "Team 1";
}
if (isset($matchval["teamtitle2"]) && $matchval["teamtitle2"] != "") {
$team2 = $matchval["teamtitle2"];
} else {
$team2 = "Team 2";
}
if (isset($matchval["team1_score"]) && $matchval["team1_score"] != "") {
$team1score = $matchval["team1_score"];
} else {
$team1score = 0;
;
}
if (isset($matchval["team2_score"]) && $matchval["team2_score"] != "") {
$team2score = $matchval["team2_score"];
} else {
$team2score = 0;
;
}
?>
[
[{"name": "<?php echo $team1; ?>", "id": "<?php echo $team1; ?>", "seed": 1, "score": "<?php echo $team1score; ?>"}, {"name": "<?php echo $team2; ?>", "id": "<?php echo $team2; ?>", "seed": 2, "score": "<?php echo $team2score; ?>"}],
],
<?php } ?>
];
$(".my_gracket").gracket({src: win.TestData<?php echo $cnt; ?>});
})(window, document, jQuery);
</script>
It is giving me output like this:-
win.TestData = [
[
[ {"name" : "Chennai super kings", "id" : "Chennai super kings", "seed" : 1, "score" : "10" }, {"name" : "Spartans", "id" : "Spartans", "seed" : 2, "score" : "5"} ],
],
[
[ {"name" : "Lions11", "id" : "Lions11", "seed" : 1, "score" : "15" }, {"name" : "Kings Xl Punjab", "id" : "Kings Xl Punjab", "seed" : 2, "score" : "10"} ],
],
[
[ {"name" : "Zimbabwe", "id" : "Zimbabwe", "seed" : 1, "score" : "15" }, {"name" : "Red Steel", "id" : "Red Steel", "seed" : 2, "score" : "5"} ],
],
[
[ {"name" : "Zimbabwe", "id" : "Zimbabwe", "seed" : 1, "score" : "10" }, {"name" : "Chennai super kings", "id" : "Chennai super kings", "seed" : 2, "score" : "15"} ],
],
[
[ {"name" : "Team 1", "id" : "Team 1", "seed" : 1, "score" : "0" }, {"name" : "Team 2", "id" : "Team 2", "seed" : 2, "score" : "0"} ],
],
];
which is not correct. The output should be like this:-
win.TestData = [
[
[ {"name" : "Chennai super kings", "id" : "Chennai super kings", "seed" : 1, "score" : "10" }, {"name" : "Spartans", "id" : "Spartans", "seed" : 2, "score" : "5"} ],
[ {"name" : "Lions11", "id" : "Lions11", "seed" : 1, "score" : "15" }, {"name" : "Kings Xl Punjab", "id" : "Kings Xl Punjab", "seed" : 2, "score" : "10"} ],
[ {"name" : "Zimbabwe", "id" : "Zimbabwe", "seed" : 1, "score" : "15" }, {"name" : "Red Steel", "id" : "Red Steel", "seed" : 2, "score" : "5"} ],
],
[
[ {"name" : "Zimbabwe", "id" : "Zimbabwe", "seed" : 1, "score" : "10" }, {"name" : "Chennai super kings", "id" : "Chennai super kings", "seed" : 2, "score" : "15"} ],
],
[
[ {"name" : "Team 1", "id" : "Team 1", "seed" : 1, "score" : "0" }, {"name" : "Team 2", "id" : "Team 2", "seed" : 2, "score" : "0"} ],
],
];
Round 1 matches should be in first array then second and the so on.
One approach is if you first build the data into the right structure in PHP, which makes it easier to manipulate. Then you can output it as JSON using json_encode.
<?php
$rounds = [];
$output = [];
// Format data and sort by round
foreach ($roundmatcharr as $matchval) {
$match1 = new stdClass();
$match1->name = $matchval['teamtitle1'];
$match1->id = $matchval['teamtitle1'];
$match1->seed = 1;
$match1->score = $matchval['team1_score'];
$match2 = new stdClass();
$match2->name = $matchval['teamtitle2'];
$match2->id = $matchval['teamtitle2'];
$match2->seed = 2;
$match2->score = $matchval['team2_score'];
$rounds[$matchval['round_number']][] = [$match1, $match2];
}
// Extra loop to clean up round numbers
foreach ($rounds as $round) {
$output[] = $round;
}
?>
<script type="text/javascript">
(function (win, doc, $) {
win.TestData<?php echo $cnt; ?> = <?php echo json_encode($output); ?>;
$(".my_gracket").gracket({src: win.TestData<?php echo $cnt; ?>});
})(window, document, jQuery);
</script>

Mongo php Can't canonicalize query: BadValue bad geo query'

I'm trying to build a query to search geospatial data in mongo using php-mongo library.
Object structure
{
"_id" : ObjectId("536ecef59bdc8977f1e9c06f"),
"location" : {
"type" : "Point",
"coordinates" : [
[
-74.220408,
40.727703
]
]
},
"bounds" : {
"type" : "Polygon",
"coordinates" : [
[
[
-74.221403,
40.728457
],
[
-74.219413,
40.728457
],
[
-74.219413,
40.726949
],
[
-74.221403,
40.726949
],
[
-74.221403,
40.728457
]
]
]
},
"tile" : {
"type" : "Polygon",
"coordinates" : [
[
[
-74.220498,
40.727772
],
[
-74.220318,
40.727772
],
[
-74.220318,
40.727634
],
[
-74.220498,
40.727634
],
[
-74.220498,
40.727772
]
]
]
},
"status" : "2",
"dev" : "0"
}
Indexes
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "atlantic.Analyzer_Marks"
},
{
"v" : 1,
"key" : {
"location.coordinates" : "2d"
},
"name" : "location.coordinates_2d",
"ns" : "atlantic.Analyzer_Marks"
},
{
"v" : 1,
"key" : {
"bounds" : "2dsphere"
},
"name" : "bounds_2dsphere",
"ns" : "atlantic.Analyzer_Marks",
"2dsphereIndexVersion" : 2
},
{
"v" : 1,
"key" : {
"tile" : "2dsphere"
},
"name" : "tile_2dsphere",
"ns" : "atlantic.Analyzer_Marks",
"2dsphereIndexVersion" : 2
}
]
$mongo = new MongoClient("mongodb://someserver.com:27017");
$marks = $mongo->selectDB('atlantic');
$q = array('bounds' => array(
'$geoWithin' => array(
'$geometry' => array(
'type' => 'Polygon',
'coordinates' => array(array(
array(40.125246,-74.327963),
array(40.125246,-74.325989),
array(40.123738,-74.325989),
array(40.123738,-74.327963),
array(40.125246,-74.327963)
))
)
)
)
);
$marks = new MongoCollection($marks,'Analyzer_Marks');
$marks = $marks->find($q);
//var_dump($marks);
$results = array();
if(!empty($marks)){
foreach($marks as $mark) {
$results[] = array(
"location" => $mark['location'],
"tile" => $mark['tile'],
"status" => $mark['status']
);
}
}
This is the error I get:
Fatal error: Uncaught exception 'MongoCursorException' with
message 'someserver.com:27017: Can't canonicalize query: BadValue bad
geo query' in /var/www/html/one-call/lib/somefile.php:97
MongoDB Version 2.6.1
I can reproduce that error. I think you are missing one more array call wrapping around the array of coordinates:
$mongo = new MongoClient("mongodb://someserver.com:27017");
$marks = $mongo->selectDB('atlantic');
$q = array('bounds' => array(
'$geoWithin' => array(
'$geometry' => array(
'type' => 'Polygon',
'coordinates' => array(
array(
array(40.125246,-74.327963),
array(40.125246,-74.325989),
array(40.123738,-74.325989),
array(40.123738,-74.327963),
array(40.125246,-74.327963)
)
)
)
)
)
);
after modifying the code I don't receive that error anymore

Can't find proper criteria to update document in mongoDB

I have followed model stored in mongoDB:
{
"_id" : "some_table_name",
"content" : [{
"id" : "1",
"locname" : "KKH"
}, {
"id" : "2",
"locname" : "Singapore National Eye Centre"
}]
}
I try to find criteria to update 2nd element (id=2) aka add new String.
"new_element" : "foo"
So new view should be:
{
"_id" : "some_table_name",
"content" : [{
"id" : "1",
"locname" : "KKH"
}, {
"id" : "2",
"locname" : "Singapore National Eye Centre"
"new_element" : "foo"
}]
}
Form PHP
When I try to find 2nd node by id I use:
$array = $collection_bios2->findOne(
array("_id" => "some_table_name", "content.id" => "2"),
array("_id" => 0, "content.$" => 1)
);
But when I try to update it, new node enters under content:
$newdata = array('$set' => array("new_element" => "foo"));
$collection_bios2->update(
array("_id" => "some_table_name", "content.id" => "2"),
$newdata
);
I get:
{
"_id" : "some_table_name",
"content" : [{
"id" : "1",
"locname" : "KKH"
}, {
"id" : "2",
"locname" : "Singapore National Eye Centre"
}],
"new_element" : "foo"
}
Whats wrong in my implementation?
Please, help,
Maxim
You need to use the positional operator here:
array('$set'=>array('content.$.new_element':'foo'))
You can read more about it here: http://docs.mongodb.org/manual/reference/operator/positional/

Categories