I want to create a chart. Using the library below.
https://charts.erik.cat/adding_datasets.html#database-eloquent-example-2
Query that dynamically reports the number of users for the last 6 months
(with month rows
Sample:
January = 1,
February = 2,
March = 3
...)
The output I want is:
$user_count_chart = [
"2" => 30,
"3" => 41,
"4" => 50,
"5" => 62,
"6" => 72,
"7" => 150,
];
**
key: month value
value: number of users
**
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('email')->unique();
$table->string('password');
$table->dateTime('email_verified_at')->nullable();
$table->rememberToken();
$table->timestamps();
});
return User::groupBy('date')
->orderBy('date', 'desc')
->take(6)
->get([
DB::raw('MONTH(created_at) as date'),
DB::raw('count(id) as total')
])
->pluck('total', 'date');
One important thing you may need to be careful is, missing months. Let's say if there isn't any user on march then your chart may not work as you expected. Please check this answer to overcome this "possible" problem.
Can use groupBy() function of Laravel Collection.
$user_count_chat = User::all()
->groupBy(function ($user) {
return $user->created_at->month;
})
->map(function ($group) {
return $group->count();
})
EDIT
Be carefull, I think month number is not good enough, Because 2019-Jan and 2020-Jan both has the same month number, but they are not the same, My advice is use 'year-month'
Related
Hello great people of SO!
I hope you all have a good day and have a good health
Note: I'm not good at SQL
Sorry for bad english, but I will try my best to explain my issue
I'm using Laravel v8.x for my app, and after setting up model relationships, events, queues, etc, now I'm working for SQL
ATM, I have 2 Models,
User
Post
Relationships:
User hasMany Post
User belongsToMany User (Block)
User belongsToMany User (Follow)
Post belongsTo User
Database:
5 record for User
2 record for Block
3 records for Post
Table: (Using faker)
users
[
{ id: 1, name: 'Jonathan Beatrice', username: 'kiana.fay', ... },
{ id: 2, name: 'Lacey Kirlin', username: 'kenna.turner', ... },
{ id: 3, name: 'Alexander Schiller', username: 'cassandra95', ... },
{ id: 4, name: 'Daniel Wickozky', username: 'nkoepp', ... },
{ id: 5, name: 'Maymie Lehner', username: 'frami.felton', ... }
]
block
[
{ id: 1, by_id: 1, to_id: 2 }, // User #1 block user #2
{ id: 2, by_id: 4, to_id: 1 } // User #4 block user #1
]
posts
[
{ id: 1, user_id: 2, body: 'Test post', ... },
{ id: 2, user_id: 5, body: 'Lorem ipsum dolor sit amet ...', ... },
{ id: 3, user_id: 4, body: 'ABCD festival soon! ...', ... },
]
Everything works fine and smooth
Now that I want to implement search system, I have a problem, since I'm not good with SQL
Here's my code
SearchController.php
use ...;
use ...;
...
public function posts(Request $request)
{
// For testing purpose
$user = User::with(['userBlocks', 'blocksUser'])->find(1);
// Get all id of user that $user block
// return [2]
$user_blocks = $user->userBlocks->pluck('pivot')->pluck('to_id')->toArray();
// Get all id of user that block $user
// return [4]
$blocks_user = $user->blocksUser->pluck('pivot')->pluck('by_id')->toArray();
// Merge all ids above (must be unique())
// return [2, 4]
$blocks = array_merge($user_blocks, $blocks_user);
// .../search?q=xxx
$query = $request->query('q');
$sql = Post::query();
// Search for posts that has `posts`.`body` LIKE ? ($query)
$sql->where('body', 'LIKE', "%$query%");
// This is where I got confused
$sql->orWhereHas('user', function ($post_user) use ($blocks, $query) {
$post_user
->whereNotIn('id', $blocks) // Exclude posts that has user and their id not in (x, x, x, x, ... ; $block variable above)
->where('name', 'LIKE', "%$query%") // Find user that has name LIKE ? ($query)
->orWhere('username', 'LIKE', "%$query%"); // or Find user that has username LIKE ? ($query)
});
$sql->orderBy('created_at', 'DESC');
$sql->with(['user']);
$posts = $sql->simplePaginate(10, ['*'], 'p');
return $posts;
}
I run the code, .../search?q=e
Note:
All users has alphabet E in their names
And also all posts has alphabet E in their body
We (as User #1), block User #2, and User #4, block us (User #1)
Result: Controller returned all posts
This is the query when I use DB::enableQueryLog() and DB::getQueryLog()
SELECT
*
FROM
`posts`
WHERE `body` LIKE ?
AND EXISTS
(SELECT
*
FROM
`users`
WHERE `posts`.`user_id` = `users`.`id`
AND (
`id` NOT IN (?)
AND `username` LIKE ?
OR `name` LIKE ?
))
ORDER BY `created_at` ASC
LIMIT 11 OFFSET 0
Goal: Search all posts that has body LIKE ?, OR posts that has user; username LIKE ? or name LIKE ? (But also exclude the user we block and the user that block us
Thanks in advance
If there's any unclear explanation, I will edit it A.S.A.P
If I run on my recent laravel install, with my proposed change for one of your issues, version 7.19.1, I get this query:
SELECT
*
FROM
`posts`
WHERE `body` LIKE ?
OR EXISTS <- line of interest
(SELECT
*
FROM
`users`
WHERE `posts`.`user_id` = `users`.`id`
AND (
`id` NOT IN (?)
AND (`username` LIKE ?
OR `name` LIKE ?) <- extra brackets ive added
))
ORDER BY `created_at` ASC
LIMIT 11 OFFSET 0
Have a look at the line of interest, and compare it with the query your version of laravel is running. The AND EXISTS line is being incorrectly generated by laravel. OrWhereHas isnt behaving correctly in your version, I can't find the release number to see where it was fixed.
Id recommend upgrading to latest if possible, but thats not always an option. I've had a dig around, and it looks like the user in this question here encountered a similar problem:
WhereHas() / orWhereHas not constraining the query as expected
You can try moving your $sql->with(['user']); to before you OrWhereHas clause. I'm not sure if that will change it to OR, but its worth a try.
Second thing, I've added whereNested to your OR clause to ensure the precedence is correct, which adds the extra brackets in the query above, as in you dont want:
(`id` NOT IN (1, 2, 3)
AND `name` LIKE % test %)
OR `username` LIKE % test %
Since then it would include your blocked posts in the exists clause.
So final changes look like this, which I think fufills your description:
$sql->with(['user']); //deleted from original position and move here
$sql->where('body', 'LIKE', "%$query%")->whereNotIn('id', $blocks); //additional line
$sql->orWhereHas('ambience', function ($post_user) use ($blocks, $query) {
$post_user
->whereNotIn('id', $blocks);
$post_user->whereNested(function($post_user) use ($query) { //new bit
$post_user->where('name', 'LIKE', "%$query%")
->orWhere('username', 'LIKE', "%$query%");
});
});
const mongoconection =url;
const agenda = new Agenda({
db: {
address: mongoconection,
collection: "agendajobs",
option: { useUnifiedTopology: true }
}
});
new Promise(resolve=> agenda.once('ready', resolve));
agenda.define("say hello", job => {
console.log('hello');
});
(async function() {
await agenda.start();
await agenda.schedule(4/2/2020, 'say hello');
//repeat every
})();
how can I pass the dynamic date to the agenda?``
it's falling if I give in this formate 4/2/2020
If I give 5 minutes or even once a week if working
can anyone help me how to give time and specified date
Since schedule(when, name, [data]) as per the documentation
[s]chedules a job to run name once at a given time. when can be a Date or a String such as tomorrow at 5pm.
You need to provide a Date object instead of String.
The way to do it as per Date MDN documentation is new Date(2020, 1, 4) (assuming you meant February and not April) so your line could be:
agenda.schedule(new Date(2020, 1, 4), 'say hello');
In Aerospike, I need run a query based on mapkeys values, filtering by records having 2 values
My predicate for filter by one value looks like this, and it work
predexp.stringValue('t3'),
predexp.stringVar('item'),
predexp.stringEqual(),
predexp.mapBin('category'),
predexp.mapKeyIterateAnd('item')
I tried duplicating the code, using the "and()" method, etc but all tries return error code 4
some help, please?
I'm not entirely sure I understand your question. I think you want to find all records that have a map bin categories that has at least two keys t3 and some other specific value. Correct?
Here is how you would do that:
const as = require('aerospike')
as.connect().then(async client => {
await client.put(new as.Key('test', 'qq', 1), { categories: { red: 1, blue: 2, green: 3 } })
await client.put(new as.Key('test', 'qq', 2), { categories: { blue: 2, green: 3, yellow: 4 } })
const query = client.query('test', 'qq')
query.predexp = [
// Find any record that has a category blue.
as.predexp.stringValue('blue'),
as.predexp.stringVar('cat'),
as.predexp.stringEqual(),
as.predexp.mapBin('categories'),
as.predexp.mapKeyIterateOr('cat'),
// Find any record that has a category yellow.
as.predexp.stringValue('yellow'),
as.predexp.stringVar('cat'),
as.predexp.stringEqual(),
as.predexp.mapBin('categories'),
as.predexp.mapKeyIterateOr('cat'),
// Now combine the two expression using and() to find records with categories blue AND yellow.
// Use or(2) if you want to find records that have categories blue OR yellow.
as.predexp.and(2)
]
// prints [ { green: 3, yellow: 4, blue: 2 } ]
await query.results()
.then(records => records.map(r => r.bins.categories))
.then(console.log)
client.close()
})
Note that I'm using mapKeyIterateOr instead of mapKeyIterateAnd. That's because of each of the two subexpressions, I want any key of the categories map to be blue/yellow. If you use mapKeyIterateAnd that means you want every key of the map to meet your condition.
For this project i need for the week to start on monday opposed to sunday,
and the documentation of the vue component doesn't say if it's possible. Is there a way to modify it?
Thanks in advance
I managed it by extending the plugin and overwriting startMonthDay and startNextMonthDay computed properties to match monday as a starting weekday.
Code used below:
<script>
import VueRangedatePicker from 'vue-rangedate-picker';
export default{
name:'selector-fecha',
extends: VueRangedatePicker,
data: function(){
return{
}
},
computed: {
startMonthDay:function(){
return new Date(this.activeYearStart,this.activeMonthStart,0).getDay()
},
startNextMonthDay:function(){
return new Date(this.activeYearStart,this.startNextActiveMonth,0).getDay()
},
}
}
</script>
Thanks for your answers
It does not appear to a straight forward way to change the ordering of the calendar. I would go with a package like this that is more supported, more flexible and doesn't have a failing build.
Highlight example
<script>
var state = {
highlighted: {
to: new Date(2016, 0, 5), // Highlight all dates up to specific date
from: new Date(2016, 0, 26), // Highlight all dates after specific date
days: [6, 0], // Highlight Saturday's and Sunday's
daysOfMonth: [15, 20, 31], // Highlight 15th, 20th and 31st of each month
dates: [ // Highlight an array of dates
new Date(2016, 9, 16),
new Date(2016, 9, 17),
new Date(2016, 9, 18)
],
// a custom function that returns true of the date is highlighted
// this can be used for wiring you own logic to highlight a date if none
// of the above conditions serve your purpose
// this function should accept a date and return true if is highlighted
customPredictor: function(date) {
// highlights the date if it is a multiple of 4
if(date.getDate() % 4 == 0){
return true
}
},
includeDisabled: true // Highlight disabled dates
}
}
</script>
<datepicker :highlighted="state.highlighted"></datepicker>
I am using the following queries in a customer model call to obtain my desired set of transactions.
transactions = sub_account.transactions
transaction_items = transactions.map{|transaction| [transaction.transaction_items]}
However, this is returning an array of an array of hashes. From the rails console
[ [# <TransactionItem id: 29, amount: 20>, #<TransactionItem id: 35, amount: 40>],<br>
[# <TransactionItem id: 31, amount: 30>, #<TransactionItem id: 38, amount: 30>],<br>
[# <TransactionItem id: 43, amount: 30>, #<TransactionItem id: 21, amount: 40>],<br>
]
This process works well. But now I am trying to run a where query on transaction_items but can't becuase they're embedded in the array. Here is my final desired query that I am unable to run.
transaction_items.where(:amount => 30).sum("amount")
I know you can Zip an array, but can you unzip it? I can't find any documentation on it. If no unzip, can I adapt the where query to work on the embedded arrays?
Thanks.
What about:
transactions_items = []
transactions.each{|n|transactions_items = transactions_items.concat(n.transaction_items)}
Assuming that transactions.transactions_items is an array.
.each applies the block to each item, which concats the transactions_items of the current element n to the array transactions_items.
and
sum = 0
toSum = transactions_items.where(:amount => 30)
toSum.each{|transaction_item|sum += transaction_item.amount}
or
sum = 0
toSum = transactions_items.where(:amount => 30)
toSum.inject{|sum, transaction_item| sum + transaction_item.amount}
See How to sum array of numbers in Ruby?