I have two queries.
$createdServer = Server::where('created_at', '>=', \Carbon\Carbon::now()->subMonth())
->selectRaw('COUNT(id) as createserver, DATE(created_at) as date,DAY(created_at) as day')
->groupBy('day', 'date')
->orderBy('date', 'ASC')
->orderBy('day', 'ASC')
->get();
$deletedServer = Server::where('deleted_at', '>=', \Carbon\Carbon::now()->subMonth())
->selectRaw('COUNT(id) as deleteserver, DATE(deleted_at) as date,DAY(deleted_at) as day')
->groupBy('day', 'date')
->orderBy('date', 'ASC')
->orderBy('day', 'ASC')
->onlyTrashed()
->get();
The output is:
"deletedServer": [
{
"deleteserver": 1,
"date": "2019-04-29",
"day": 29
}
],
"createdServer": [
{
"createserver": 2,
"date": "2019-04-29",
"day": 29
}
],
My requirement is:
"allServer": [
{
"deleteserver": 1,
"createserver": 2,
"date": "2019-04-29",
"day": 29
}
],
deleteServer and createServer count data in database.
You can retrieve with below code:
$allSevers = collect([
"deleteserver" => $deleteServer->count(), // retrieving the deleteServer count
"createserver" => $createServer->count(), // retrieving the createServer count
"date" => date('Y-m-d'), //date format in Year - Month - Date
"day" => date('j') // date format for mday
]);
merge function would solve the issue in your current case: link
$merged = $createdServer->merge($deletedServer);
$merged->all();
Edit:
$merged = $createdServer[0]->merge($deletedServer[0]);
$merged->all();
Related
I want to get the sum of prices from contract table and sum of transactions together connected to user id. And how can i use where in this.
Table Contracts:
[
{
"id": 1,
"user_id":97,
"price":"100"
},
{
"id": 2,
"user_id":97,
"price":"200"
},
{
"id": 3,
"user_id":97,
"price":"300"
}
]
Table Transactions:
[
{
"id": 1,
"user_id":97,
"sum":"100"
},
{
"id": 2,
"user_id":97,
"sum":"200"
},
{
"id": 3,
"user_id":97,
"sum":"300"
}
]
My query:
$query = User::where([
['contracts_sum', '<', 'transactions_sum'],
])
->join('contracts', 'contracts.user_id', '=','users.id')
->join('transactions', 'users.id', '=','transactions.user_id')
->groupBy(['users.id'])
->select(
'users.id', 'users.name',
DB::raw('SUM(contracts.price) AS contracts_sum'),
DB::raw('SUM(transactions.sum) AS transactions_sum'),
)
->get();
But this variant returns sum multiplied to count of transactions table rows like this:
[
{
"id":97,
"name":"JOHN",
"contracts_sum":"1800",
"transactions_sum":"1800"
}
]
But i would like to get the data in this kind of form:
[
{
"id":97,
"name":"JOHN",
"contracts_sum":"600",
"transactions_sum":"600"
}
]
My advice would be to make use of laravel's relation feature, as it would make it a lot easier.
class User
{
public function transactions()
{
return $this->hasMany(Transaction::class, 'user_id', 'id');
}
public function contracts()
{
return $this->hasMany(Contract::class, 'user_id', 'id');
}
}
Then, in your controller, you could do the following:
$user = User::where('id', 97)
->withSum('contracts', 'price')
->withSum('transactions', 'sum')
->get();
return [
'id' => $user->id,
'name' => $user->name,
'contracts_sum' => $user->transactions_sum_sum,
'transactions_sum' => $user->contracts_sum_price
];
Not only does this look a lot cleaner, the query will be more efficient as well. More information on the aggregate functions can be found in the laravel documentation.
I am getting objects response like this:
"facilities": [
[
{
"facility_id": 1,
"speciality_id": null,
"is_facility_supervisor": 0,
"priv_key": "can_add_doctor,can_view_doctor"
}
],
{
"name": "Patient",
"role_id": 7
}
]
I want name and role_id into facilities and i want expected output like this
"facilities": [
[
{
"facility_id": 1,
"speciality_id": null,
"is_facility_supervisor": 0,
"priv_key": "can_add_doctor,can_view_doctor",
"name": "Patient",
"role_id": 7
}
],
]
How i can achieve this output name and role_id is in separate object but i want in one object like i shared.
My Code:
$specialities = DB::table('user_facility')
->select('user_facility.facility_id','user_facility.speciality_id','user_facility.is_facility_supervisor','user_facility.priv_key')
->where('user_id',$currentUser->id)->get();
$roles = DB::table('roles')
->join('user_facility', 'roles.id', 'user_facility.role_id')
->where('user_facility.user_id', Auth::user()->id)
->select('roles.name','user_facility.role_id')->first();
$superadmin = $is_super_admin->is_super_admin;
$specialities = (object) $speciality_id;
$response = ['is_super_admin' => $superadmin, 'facilities' => array_merge([$specialities,$roles])];
Your help will be highly appreciated?
How about:
$specialitiesAndRoles = DB::table('roles')
->join('user_facility', 'roles.id', 'user_facility.role_id')
->where('user_facility.user_id', Auth::user()->id)
->select('user_facility.facility_id','user_facility.speciality_id','user_facility.is_facility_supervisor','user_facility.priv_key','roles.name','user_facility.role_id')
->get();
When you are anyway joining both tables. Just select everything from the joined table. Please check/add if you have any more where clauses.
I am trying to get following data from table
Count of registered users in each date
User details
I am trying following script to get that
$users = User::select(DB::raw('count(id) as agents, left(DATE(created_at),10) as registeredDate'))
->whereHas('roles', function($q){
$q->where('name', '=', 'agent');
})
->offset($start)
->limit($limit)
->orderBy($order,'DESC')
->groupBy('registeredDate')
->get();
Above query is returning the Count of registered users in each date
if($users){
foreach($users as $r){
$nestedData['agents'] = $r->agents;
$nestedData['date'] = date('d M Y',strtotime($r->registeredDate));
$data[] = $nestedData;
}
}
But I wanted to get users details also in the same query. My desired output is
'data' => [
[
"agents" => "13",
"date" => "12 Jan 2019",
"nested_data" => [
[
'full_name' => 'john',
'status' => 'active',
'email' => 'john#gmail.com',
],
[
'full_name' => 'John',
'status' => 'active',
'email' => 'john2#gmail.com',
]
]
]
]
Can someone kindly guide me how to achieve it. I would like to appreciate. Thanks
Change your query as:
$users = User::select(DB::raw('count(id) as agents, left(DATE(created_at),10) as registeredDate'))
->whereHas('roles', function($q){
$q->where('name', '=', 'agent');
})
->offset($start)
->limit($limit)
->orderBy($order,'DESC')
->get();
Change your foreach loop as:
if($users){
foreach($users as $user){
$date = date('d M Y',strtotime($r->registeredDate));
$data[$date]['date'] = $date;
$data[$date]['nestedData'][] = ['first_name' => $user->first_name, 'status' => $user->status, 'email' => $user->email];
$data[$date]['agents'] = count($data[$date]['nestedData']);
}
}
I'm trying to adjust the timezone with date aggregation operators.
I need to make -7 hours adjustment on the $signs.timestamp field.
This is my code:
function statsSignatures() {
$cursor = $this->db->collection->users->aggregate(
array('$unwind' => '$signs'),
array('$project'=>array(
'signs'=>'$signs',
'y'=>array('$year'=>'$signs.timestamp'),
'm'=>array('$month'=>'$signs.timestamp'),
'd'=>array('$dayOfMonth'=>'$signs.timestamp'),
'h'=>array('$hour'=>'$signs.timestamp')
)),
array('$group'=>array(
'_id'=>array('year'=>'$y','month'=>'$m','day'=>'$d','hour'=>'$h'),
'total'=>array('$sum'=>1)
)),
array('$sort'=>array(
'_id.year'=>1,
'_id.month'=>1,
'_id.day'=>1,
'_id.hour'=>1
))
);
return $cursor['result'];
}
I'm using MongoDB version 2.6.3.
Thank you a lot !
You can use $project with $subtract operator to make a -7 hour adjustment to a Date field:
{
$project : {
ts : { $subtract : [ "$signs.timestamp", 25200000 ] }
}
}
// 25200000 == 1000 milis x 60 sec x 60 mins x 7 h
The projected field ts is a Date that's offset by -7 hours.
Edit
This is the correct PHP syntax when using $subtract.
array(
'$project' => array(
'ts' => array('$subtract' => array('$signs.timestamp', 25200000))
)
)
Subtract accepts an array of values, not a key=>value pair.
I'm not sure why, but I'm getting "exception: invalid operator '$signs.timestamp'" if i'm trying to subtract this in php like this code:
$cursor = $app['mdb']->changemi->users->aggregate(
array('$unwind' => '$signs'),
array('$project' => array(
'ts'=>array('$subtract'=>array(
'$signs.timestamp'=> 25200000
))
)),
array('$project'=>array(
'y'=>array('$year'=>'$ts'),
'm'=>array('$month'=>'$ts'),
'd'=>array('$dayOfMonth'=>'$ts'),
'h'=>array('$hour'=>'$ts')
)),
array('$group'=>array(
'_id'=>array('year'=>'$y','month'=>'$m','day'=>'$d','hour'=>'$h'),
'total'=>array('$sum'=>1)
)),
array('$sort'=>array(
'_id.year'=>1,
'_id.month'=>1,
'_id.day'=>1,
'_id.hour'=>1
))
);
So I came with 2 workarounds:
backend php. json_decode
$cursor = $app['mdb']->changemi->users->aggregate(
array('$unwind' => '$signs'),
json_decode('{"$project" : {"ts" : { "$subtract" : [ "$signs.timestamp", 25200000 ] }}}',true),
array('$project'=>array(
'y'=>array('$year'=>'$ts'),
'm'=>array('$month'=>'$ts'),
'd'=>array('$dayOfMonth'=>'$ts'),
'h'=>array('$hour'=>'$ts')
)),
array('$group'=>array(
'_id'=>array('year'=>'$y','month'=>'$m','day'=>'$d','hour'=>'$h'),
'total'=>array('$sum'=>1)
)),
array('$sort'=>array(
'_id.year'=>1,
'_id.month'=>1,
'_id.day'=>1,
'_id.hour'=>1
))
);
frontend javascript (minusHours)
Date.prototype.minusHours= function(h){
this.setHours(this.getHours()-h);
return this;
}
...
"date": new Date({{ i._id.year }}, {{ i._id.month -1 }}, {{ i._id.day }}, {{ i._id.hour }}, 0, 0, 0).minusHours(7),
Here is what worked for me. Instead of doing the timezone conversion in the 'project', I just convert the timestamp while grouping.
group._id = {
year: { $year : [{ $subtract: [ "$timestamp", 25200000 ]}] },
month: { $month : [{ $subtract: [ "$timestamp", 25200000 ]}] },
day: { $dayOfMonth : [{ $subtract: [ "$timestamp", 25200000 ]}] }
};
group.count = {
$sum : 1
};
There's no need to close some objects in array, this way worked for me:
group._id = {
year: { $year : { $subtract: [ "$timestamp", 25200000 ]}},
month: { $month : { $subtract: [ "$timestamp", 25200000 ]}},
day: { $dayOfMonth : { $subtract: [ "$timestamp", 25200000 ]}}
};
group.count = {
$sum : 1
};
Is there a query to select documents based only on month or year in MongoDB, something like the equivalent for the following code in mysql;
$q="SELECT * FROM projects WHERE YEAR(Date) = 2011 AND MONTH(Date) = 5";
I am looking for the MongoDB equivalent, can anyone help?
Use the aggregation framework to get the query, in particular the Date Aggregation Operators $year and $month. The aggregation pipeline that gives you the above query would look like this:
var pipeline = [
{
"$project": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
"other_fields": 1
}
},
{
"$match": {
"year": 2011,
"month": 5
}
}
]
db.project.aggregate(pipeline);
The equivalent PHP query would be:
$m = new MongoClient("localhost");
$c = $m->selectDB("examples")->selectCollection("project");
$pipeline = array(
array(
'$project' => array(
"year" => array("$year" => '$date'),
"month" => array("$month" => '$date'),
"other_fields" => 1,
)
),
array(
'$match' => array(
"year" => 2011,
"month" => 5,
),
),
);
$results = $c->aggregate($pipeline);
var_dump($results);