Confused about MongoDB Query (PHP $and) - php

I have the following code in PHP to connect to my MongoDB instance:
$connection_string = "mongodb://XXXXXXX:XXXXXX#XXXXX:XXX/myDB";
$mongo_or = new Mongo($connection_string);
$db_or = $mongo_or->selectDB("myDB");
# Pick a collection
$collection_or = $db_or->myCollection;
$findArray = array('$and' => array('user.uid' => 1, 'friend_id' => 2));
$findArray2 = array('$and' => array('user.uid' => 2, 'friend_id' => 1));
$collection_or->remove($findArray);
$collection_or->remove($findArray2);
This never removes any results - even know the content is still there it never get's removed.

if you want the good structure for a $and query just json_decode this :
{
"$and" : [{
"$or" : [{
"civility" : 2
}, {
"civility" : 3
}]
}]
}

Related

Mongodb string to date conversion

Below is my sample mongodb collection
{
"_id" : ObjectId("57ed32f4070577ec56a56b9f"),
"log_id" : "180308",
"issue_id" : "108850",
"author_key" : "priyadarshinim_contus",
"timespent" : NumberLong(18000),
"comment" : "Added charts in the dashboard page of the application.",
"created_on" : "2017-08-16T18:22:04.816+0530",
"updated_on" : "2017-08-16T18:22:04.816+0530",
"started_on" : "2017-08-16T18:21:39.000+0530",
"started_date" : "2017-08-02",
"updated_date" : "2017-08-02",
"role" : "PHP",
"updated_at" : ISODate("2017-09-29T15:27:48.069Z"),
"created_at" : ISODate("2017-09-29T15:27:48.069Z"),
"status" : 1.0
}
I need to get records with help of started_date , by default I will give two dates in that i will check $gt and $lt of started date .
$current_date = '2017-08-31';
$sixmonthfromcurrent ='2017-08-01';
$worklogs = Worklog::raw ( function ($collection) use ($issue_jira_id, $current_date, $sixmonthfromcurrent) {
return $collection->aggregate ( [
['$match' => ['issue_id' => ['$in' => $issue_jira_id],
'started_date' => ['$lte' => $current_date,'$gte' => $sixmonthfromcurrent]
]
],
['$group' => ['issue_id' => ['$push' => '$issue_id'],
'_id' => ['year' => ['$year' => '$started_date'],
'week' => ['$week' => '$started_date'],'resource_key' => '$author_key'],
'sum' => array ('$sum' => '$timespent')]
],
[ '$sort' => ['_id' => 1]
]
] );
} );
If I run this query I am getting this type of error:
Can't convert from BSON type string to Date
How to rectify this error?
The only field in your $group that I see as troubling is the field week.
The year you could extract by doing a $project before your $group aggregation:
$project: {
year: { $substr: [ "$started_date", 0, 4 ] },
issue_id: 1,
author_key: 1,
timespent: 1
}
if you know that the date string will always come at this format. Of course you cannot do a substr operation for finding out the week.
It would be easy though if your field started_date would be an actual ISODate(), then you could use exactly what you wrote as you probably already saw in the documentation.
If you need the field week very bad, which I imagine you do, then I'd suggest you convert your field started_date to an ISODate().
You can do that with a bulkWrite:
db = db.getSiblingDB('yourDatabaseName');
var requests = [];
db.yourCollectionName.find().forEach(doc => {
var date = yourFunctionThatConvertsStringToDate(doc.started_date);
requests.push( {
'updateOne': {
'filter': { '_id': doc._id },
'update': { '$set': {
"started_date": date
} }
}
});
if (requests.length === 500) {
db.yourCollectionName.bulkWrite(requests);
requests = [];
}
});
if(requests.length > 0) {
db.yourCollectionName.bulkWrite(requests);
}
Load this script directly on your mongodb server and execute there.
Hope this helps.

PHP Mongo aggregate match regex

Performing a query that simulates a 'like/mysql' searching for teams on the name of the team
Team document structure
{
"_id": 9,
"name": "azerty",
"tag": "dsfds",
"desc": "ggdfgsdfgdfgdf",
"captain": 8,
"coach": 8,
"members": [{
"date_joined": "2016-03-31 15:22:09",
"user_id": 8
}, {
"date_joined": "2016-03-31 19:22:35",
"user_id": 9
}],
"current_invites": [{
"invite_id": 21,
"username": "Nikki",
"user_id": "9",
"status": 1,
"date_invited": "2016-03-31 18:32:40"
}, {
"invite_id": 22,
"username": "Nikki",
"user_id": "9",
"status": 2,
"date_invited": "2016-03-31 18:33:16"
}]
}
PHP Code =
$q = '/.*'.$q.'*./';
$result = $this->coll->aggregate(
array('$match' => array('name' => $q)),
array('$project' => array('name' => 1,'members' => array('$size' => '$members'))));
Feels like I'm going mad not knowing how to fix this.
Have used regex before after migrating to mongo but not with the combination of agg-match.
in my case i am finding the aggregated result in which you can not set the where clause so use the aggregated functions like $sort $unwind $orderby and so on i am using the all of the above mention and have the problem with the like stuff to match the string like %str% here my code in which i implement the like using $match with MongoRegex
public function getRecords($table,$where = array(),$like_key = false,$like_value = false,$offset = 1,$limit = 10,$order_column = false,$order_type = false, $isAggregate=false,$pipeline=array()){
$temp = $this->getMongoDb()->where($where);
if($like_key && $like_value){
$temp = $temp->like($like_key,$like_value);
// this like filter is for aggregated result work both on normal get record or by aggregated result
$pipeline[]=array(
'$match' => array( $like_key => new MongoRegex( "/$like_value/i" ) )
);
}
if($order_column && $order_type){
$order_by = array();
$order_by[$order_column] = $order_type;
$temp = $temp->order_by($order_by);
$pipeline[]=array(
'$sort'=>array($order_column => ($order_type =="desc")? -1 : 1)
);
}
I got the solution when I read the following aggregation framework go the aggregation framework
I hope you will get your solution to resolve your issue.

return multiple array through json in codeigniter

I want to return multiple array using json in codeigniter like this :
{
"countData"
[
{"flag":1,"count":3}
{"flag":0,"count":0}
{"flag":1,"count":2}
]
}
I already tried :
$faqdata=array(
'count' => $faqdata['countdata']['resultdata']['count'],
)
$listfaqcount['count_Data'][]=$faqdata;
$listfaqcount['flag'] =1;
$j_r=json_encode($listfaqcount);
echo $j_r;
Like this way for two more array .flag would be zero in else condition which I didn't mention here.
How can I do this? Please help.
Thanks in advance
You can do something like this
$listfaqcount['countData'][0] = array(
'flag' => 'flagValue',
'count' => 'countValue'
);
While you looping you change the index with your key like that
$listfaqcount['countData'][1] = array(
'flag' => 'flagValue',
'count' => 'countValue'
);
and so on and while you encoding you can do like this
echo json_encode($listfaqcount);
You need something like array_push
$array['countdata'] = [];
create our sample array sets
$somearray1 = ['flag'=>9,"count"=>5];
$somearray2 = ['flag'=>6,"count"=>6];
$somearray3 = ['flag'=>5,"count"=>7];
$somearray4 = ['flag'=>4,"count"=>8];
Basically what happens here is everytime you loop you push the array inside $array['countdata']
array_push($array['countdata'], $somearray1); //loop 1 format and push
array_push($array['countdata'], $somearray2); //loop 2 format and push
array_push($array['countdata'], $somearray3); //loop 3 format and push
array_push($array['countdata'], $somearray4); //loop 4 format and push
Print the result beautifully or prettily
print_r(json_encode($array,JSON_PRETTY_PRINT));
result would be
{
"countdata": [
{
"flag": 9,
"count": 5
},
{
"flag": 6,
"count": 6
},
{
"flag": 5,
"count": 7
},
{
"flag": 4,
"count": 8
}
]
}
this is just an example you could push your own formatted array.

How to use "group" in MongoDB with PHP?

I'm using PHP with MongoDB, How can apply below commend inside?
db.event.group({
keyf: function(doc) {
return {
year: doc.created.getFullYear(),
month: doc.created.getMonth() + 1,
day: doc.created.getDate()
}
},
reduce: function(curr, result){
result.count++;
},
initial: {count: 0}
});
I have tried below, but NOT working. Looks like not supprt keyf?
$keyf = 'function(doc){return {year: doc.created.getFullYear(), month: doc.created.getMonth()+1, day: doc.created.getDate()}}';
$initial = array('count' => 0);
$reduce = 'function(curr, result){result.count++;}';
$collection->group($keyf, $initial, $reduce);
It looks like you are basically counting the amount of documents under a date.
It should be noted that the group command has numerous flaws including:
Not officially supporting sharding (warning not to use it)
Is basically JavaScript
Is Basically a Map Reduce
Is extremely slow
that means it has since been "deprecated" in favour of the aggregation framework, which in PHP for you would be:
$db->collection->aggregate(array(
array('$group' => array(
'_id' => array(
'day' => array('$dayOfMonth' => '$created'),
'month' => array('$month' => '$created'),
'year' => array('$year' => '$created')
),
'count' => array('$sum' => 1)
))
));
To understand what operators I used etc you can look here:
http://docs.mongodb.org/manual/reference/operator/aggregation/dayOfMonth/
http://docs.mongodb.org/manual/reference/operator/aggregation/month/#exp._S_month
http://docs.mongodb.org/manual/reference/operator/aggregation/year/
http://docs.mongodb.org/manual/reference/operator/aggregation/sum/
The PHP driver does have the MongoCode class for constructing the JavaScript values that are required.
But you are actually better off using the .aggregate() command to this as it is "native* code and does not rely on the JavaScript engine. So it is much faster at producing results.
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$created" },
"month": { "$month": "$created" },
"day": { "$dayOfMonth": "$created" }
},
"count": { "$sum": 1 }
}}
])
Data Problem
So the aggregate function works are expected, but you seem to have a problem with your test data. Here is cwhat you gave:
db.post.insert({'field':'b', 'created':new Date('2014, 1, 1')});
db.post.insert({'field':'c', 'created':new Date('2014, 1, 1 11:11:11')});
db.post.insert({'field':'d', 'created':new Date('2014, 1, 1 12:00:00')});
db.post.insert({'field':'a', 'created':new Date('2014, 1, 2')});
db.post.insert({'field':'b', 'created':new Date('2014, 1, 2')})
And this produces the data:
{ "field" : "a", "created" : ISODate("2013-12-31T13:00:00Z") }
{ "field" : "b", "created" : ISODate("2013-12-31T13:00:00Z") }
{ "field" : "c", "created" : ISODate("2014-01-01T00:11:11Z") }
{ "field" : "d", "created" : ISODate("2014-01-01T01:00:00Z") }
{ "field" : "a", "created" : ISODate("2014-01-01T13:00:00Z") }
{ "field" : "b", "created" : ISODate("2014-01-01T13:00:00Z") }
So it looks like you were trying to add "hours" in the same day to test the grouping. But the arguments to Date() are not correct. You wanted this:
db.post.insert({'field':'b', 'created':new Date('2014-01-01')});
db.post.insert({'field':'c', 'created':new Date('2014-01-01 11:11:11')});
So the whole date as a string and not the "comma" separated values

laravel mongodb push element to existing array in document_

In my mongodb collection I want to push some elements to an existing array. I use jenssegers/Laravel-MongoDB - Eloquent model and Query builder to work with lavavel and mongodb.
How can I use the $push operator in jenssegers/Laravel-MongoDB?
MongoDB entry which shall be updated (RockMongo representation):
{
"_id": ObjectId("5328bc2627784fdb1a6cd398"),
"comments": {
"0": {
"id": 3,
"score": 8
}
},
"created_at": ISODate("2014-03-18T21:35:34.0Z"),
"file": {
"file_id": NumberLong(1175),
"timestamp": NumberLong(1395178534)
}
}
Hint about array representation in rockmongo and mongo shell
RockMongo and mongo shell array representation of the documents are a little bit different. Have a look at the comments-array. The above RockMongo representation appears in the mongo shell as:
{
"_id" : ObjectId("5328c33a27784f3b096cd39b"),
"comments" : [
{
"id" : 3,
"score" : 8
}
],
"created_at" : ISODate("2014-03-18T22:05:46Z"),
"file" : {
"file_id" : NumberLong(1176),
"timestamp" : NumberLong(1395180346)
}
}
As the documentation states the $push operater to push elements to an array. This works fine in the mongo-shell:
Mongo shell
db.Images.update({'file.file_id': 1175},
{ $push: { comments: { id: 3, score: 8} }
})
But in the query-builder I struggle to incorporate the $push operator. I get the error:
localhost:27017: Modified field name may not start with $
I did not find any documentation or example that showed me how to do it..
My jenssegers/Laravel-MongoDB code, that returns the error
// $file_id = 1175
public static function addComment( $file_id ) {
$image = Images::where( 'file.file_id', '=', floatval( $file_id ) )
->update( array('$push' => array( 'comments' => array( 'id' => 4, 'score' => 9 ) ) ) );
return $image;
}
Assuming everything is okay as it works in the shell then use the provided method to push instead:
Images::where('file.file_id', '=', floatval( $file_id ))
->push('comments', array( 'id' => 4, 'score' => 9 ));

Categories