I have two collections - users and chats. Each chat message has a structure like the following:
_id: ObjectId
from: ObjectId // user _id
to: ObjectId // user _id
message: String
date_created: Date
And each user has:
_id: ObjectId
name: String
username: String
// ... not important stuff
I need to fetch conversations that are only sent to me and the result should be in the following way:
{
data: [
{
"id": conversation_id,
"title": username,
"message": message_excerpt
},...
]
}
My problem is trying to get the username from the reference because I don't want to make 20 fetch queries to get 20 different usernames. I would have added the username when the conversation is first created but I can't because the username can be changed any time. This would create an inconsistency between the username and the conversation title. How should I handle this problem? This is the first time I wished there was a JOIN in Mongo.
Two possibilities:
1: Add the username to chat message documents. Like you said, if the username changes, you need to change the username on all the user's chats.
2: Do an application-level join. You don't need to do 20 queries to get the 20 names. You can first retrieve all the chats, then collect all of the user_id values and do one query. For example:
var results = [
{ "_id" : 0, "from" : 43, "to" : 86, "message" : "sup?" },
{ "_id" : 1, "from" : 99, "to" : 86, "message" : "yo" }
]
var from_users = db.users.find({ "_id" : { "$in" : results.map(function(doc) { return doc.from }) } }).toArray()
Now you can use the from_users to populate the username into results or create your desired document structure. Note that results from the $in are necessarily returned in the order of elements in the array argument to $in - this is commonly expected/desired but it's not the case.
Related
I am working with Laravel 8 and get stuck creating a custom query return client data with number of visits by month for every client
first this is the tables structure
clients table has id and name, ....etc
reports table has id , report_date and city, ...etc
report_details has id,report_id, client_id, ...etc
the relation between Report and report_details is one to one
I create a relation in Report model as following
public function reportDetails() {
return $this->hasOne(reportDetails::class, 'report_id');
}
I want to execute a query between two dates for example between 01-01-2021 and 25-03-2021 generate a JSON array and every object has with following keys
client_id, client_name, month, visits_count_by_month
I expect to get following result
[
{
"client_id": 2,
"client_name": "John",
"client_visits: [
"Jan": 5,
"Feb": 2,
"March": 0
]
},
{
"client_id": 5,
"client_name": "Mark",
"client_visits: [
"Jan": 2,
"Feb": 0,
"March": 0
]
}
]
I write the following query but I don't know how to customize it and link it with third table clients
$reports = Report::whereBetween('report_date', [$start_date, $end_date])->get();
Question: I have two tables how to fetch a customer's data using order's table user_id
"order": [
{
"id": 1,
"user_id": 4
},
{
"id": 2,
"user_id": 5
}
],
"customers": [
{
"id": 5,
"name": "Mohamed Raazi",
"phone": "777",
}
],
Following code will return only the last object of an array, i need to display all the objects from user table using a where condition in customers table
for ($x=0; $x<count($orders); $x++){
$customer = User::where('id',$orders[$x]->user_id)->get();
}
I would use the ::whereIn-method where you can provide an array of IDs to and get all the users with the provided IDs.
First you would have to reformat the $orders array that you have so that it contains only user IDs. I am guessing that you are using Eloquent to fetch the orders, then you can use the pluck-function in your Eloquent-statement:
$userIds = Order::where('statement', true)->pluck('user_id')->toArray();
Please note that the where-statement is not real, I just want to illustrate how you can call the pluck-method.
Another alternative is that you use the map function on the $orders-collection and return only user IDs:
$userIds = $orders->map(function ($order) {
return $order->user_id;
});
Once you have your user IDs in an array/collection you can use it in the whereIn-statement:
$users = Users::whereIn('id', $userIds)->get();
Then this would give you all the users that that are connected to the orders you have in your order-collection.
I try to use the Fractal library from The PHP League in my project
I have model: Object with fields id, name. It has relation prototypes as one to one.
So, model Prototype has relation Fields. Where model Fields contains fields: name, id.
Also there is separated model: ObjectFields that contains values for each object fields. For example:
object_id | value
1 1
In result I need to get output JSON:
objects : {
"id" : 1,
"name" : "Weapon",
"prototype": {
"id" : 1,
"name" : "Prototype Name",
"fields" : {
"field_name" : ObjectFields.value
}
}
}
Look please on
"fields" : {
"field_name" : ObjectFields.value
}
so, It would be field name as key and value from model ObjectFields.
Now I do request using query as:
Object::with("prototype.field.name.value");
It returns me nested output object, but I need that last 3 realations will be in one object by key field.name
I am trying to create some report filters where the user can search for profiles using any fields on the report. For example: search for any profile with firstname that starts with ann and grade that starts with vi etc.
Here is a query I have written so far:
{
from: 20,
size: 20,
query: {
filtered: {
query: {
match_all: [ ]
},
filter: {
bool: {
must: [
{
prefix: {
firstname: "ann"
}
},
{
prefix: {
grade: "vi"
}
}
]
}
}
}
},
sort: {
grade: {
order: "asc"
}
}
}
If I remove one child of must (in the bool filter), it works. But it doesn't return any results once I use more than one filters and I need to be able to use any number of entries in there.
Also, if I use should instead of must, it works. I'm not sure if I'm misunderstanding the logic, but to my understanding (in this case) must should return ONLY results with firstname that starts with ann and grade that starts with vi.
They do exist, but this query just doesn't find them.
Am I missing something here?
Thanks
Since, I cannot post comments yet. I'm answering with some assumptions.
First of all, I'm using ES 0.90.2 version and your query works fine for my inputs. However, depending on your input size and the platform that you executed your query, my answer may not be the right one.
Assumption: Number of data in the index is less than 20.
I've added following inputs to my index:
'{"name": "ann", "grade": "vi"}'
'{"name": "ann", "grade": "ii"}'
'{"name": "johan", "grade": "vi"}'
'{"name": "johan", "grade": "ii"}'
And my test query was the same as yours, and here is the result:
"hits" : {
"total" : 2,
"max_score" : null,
"hits" : [ ] // <-- see this part is blank
}
As you can see, it didn't listed hits, but there are two hits. That's because of the from:20 code segment. If you change that value, you can see some results. If you want to see all results just delete that part.
Note: Well if this is not the case, sorry for bothering :(
Hello everybody I have a document is structured like that:
{
name : abc
message:
[{
id: 4,
status : 0,
content : "abc"
},
{
id: 2,
status : 1,
content : "abc"
},
{
id: 1,
status : 1,
content : "abc"
}
]
}
How Can I get the sorted message array by id key and status = 1
I mean
{
id: 1,
status : 1,
content : "abc"
},
{
id: 2,
status : 1,
content : "abc"
},
Thank so much!
This solutin in mongo shell, should work out for you. But the aggregate framework is supported from Mongo 2.1 onwards. http://docs.mongodb.org/manual/applications/aggregation/
db.yourcollection.aggregate([{$unwind:"$message"},{$match:{"message.status":1}},{$project:{_id:0,message:1}},{$sort:{"message.id":1}}])
Since your message key is an array you have to first use the $unwind operator and then use the $match operator.
By default mongo will display the _id of the document. So if you do not want to display the _id, after matching the relevant ones, you could use the $project operator
If you don't want the name key to be displayed, simply don't specify the name key in the project part of the query. By default mongo will only display the keys whose value is 1. If the key is not mentioned it will not display it.
And then you use $sort operator, 1 for asecnding and -1 for descending.