Chat query to get only last occurrence with given parameters (most recent message in each conversation) MongoDB - mongodb

I have a chat application set up in MongoDB.
The structure of each message object in the DB is the following:
{
_id: "63dd49fdf24c2721fc4b3a84",
from: "id_of_the_sender",
to: "id_of_the_receiver",
timestamp: 2023-02-03T17:53:01.015+00:00,
message: "Text of the message"
}
Now I need to create a homescreen much like any messenger application.
It must show a list of all my conversations, with the text of the last message I exchanged with each user and its timestamp.
It also needs to lookup the user details (like photo and name) from the other collection "users", but this part I think I know how to do.
Is there a query in MongoDB that can return me that?
Thank you!

Related

How to sort by a field in a sub-collection in firebase cloud firestore in flutter

I am trying to query a cloud firestore database and i need it to return all the documents in the chats collection sorted by the timestamp field which is a field that all the documents in the messages sub-collection have.
i tried writing a query like this.
FirebaseFirestore.instance.collection("chats").orderBy("messages.timestamp", descending: true)].get(),
but it does not return any documents when actually there are some documents there.
Firestore can only order or filter on data in the documents that it returns. There is no ability to order or filter on data outside of those documents.
So if we want to order chats in the timestamp of the last message in that chat (a common use-case), you'll have to include a lastMessageTimestamp field in the chat document itself, and update that whenever a message is written in its messages subcollection. With that lastMessageTimestamp field in place in each chats document, you can then order and filter on that.
Create a new collection called messages and store all messages for every user there (with a user id field). Reference the message uid's via an array in each chat. This way you can easily query for the messages associated with a chat session then sort them.

Unable to use email as name of database in mongodb

if I do mongoose.connect('whatever/email(as DB name)'), it throws errors. Is there any way to do it? I want to make a separate DB for each email.
You can do as below.
Have a users meta collection
{
email:"a#action.com",
uniqueId: 12
}
Use this uniqueId as collection name to store details.
But this would require two calls every time - one to find user collection and another one on querying the respective collection.

Schema on mongodb for reducing API calls with two collections

Not quite sure what the best practice is if I have two collections, a user collection and a picture collection - I do not want to embed all my pictures into my user collection.
My client searches for pictures under a certain criteria. Let's say he gets 50 pictures back from the search (i.e. one single mongodb query). Each picture is associated to one user. I want the user name displayed as well. I assume there is no way to do a single search performance wise on the user collection returning the names of each user for each picture, i.e. I would have to do 50 searches. Which means, I could only avoid this extra performance load by duplicating data (next to the user_id, also the user_name) in my pictures collection?
Same question the other way around. If my client searches for users and say 50 users are returned from the search through one single query. If I want the last associated picture + title also displayed next to the user data, I would again have to add that to the users collection, otherwise I assume I need to do 50 queries to return the picture data?
Lets say the schema for your picture collection is as such:
Picture Document
{
_id: Objectid(123),
url: 'img1.jpg',
title: 'img_one',
userId: Objectid(342)
}
1) Your picture query will return documents that look like the above. You don't have to make 50 calls to get the user associated with the images. You can simply make 1 other query to the Users Collection using the user ids taken from the picture documents like such:
db.users.find({_id: {$in[userid_1,user_id2,userid_3,...,userid_n]}})
You will receive an array of user documents with the user information. You'll have to handle their display on the client afterwards. At most you'll need 2 calls.
Alternatively
You could design the schema as such:
Picture Document
{
_id: Objectid(123),
url: 'img1.jpg',
title: 'img_one',
userId: Objectid(342),
user_name:"user associated"
}
If you design it this way. You would only require 1 call, but the username won't be in sync with user collection documents. For example lets say a user changes their name. A picture that was saved before may have the old user name.
2) You could design your User Collection as such:
User Document
{
_id: Objectid(342),
name: "Steve jobs",
last_assoc_img: {
img_id: Object(342)
url: 'img_one',
title: 'last image title
}
}
You could use the same principles as mentioned above.
Assuming that you have a user id associated with every user and you're also storing that id in the picture document, then your user <=> picture is a loosely coupled relationship.
In order to not have to make 50 separate calls, you can use the $in operator given that you are able to pull out those ids and put them into a list to run the second query. Your query will basically be in English: "Look at the collection, if it's in the list of ids, give it back to me."
If you intend on doing this a lot and intend for it to scale, I'd either recommend using a relational database or a NoSQL database that can handle joins to not force you into an embedded document schema.

how to retrieve all data from a particular document in couch db?

I have a document where i am saving all the user registration information with a particular random id associated to it.
my document looks like:
_id:xyz
_rev:9-a4d476aa9f4b41879d21a7f475a2f1d5
-742566755
course:gg
passwdt:t
phone:1313
clgnme:hfhjf
address:fjhfj
-884381686
course:gg
passwdt:t
phone:1313
clgnme:hfhjf
address:fjhfj
Now, i Want to retrieve the document with all information as shown in the document.
I want that it should be shown individually as i have done with getting the values on console. but i want it acording to each id individually.
Like if i want to get data of -884381686 id and it can be anything name, address anything. it should fetch data accordingly.
**NOTE:**PROGRAMMING TO BE DONE IN GWT
You mean you want to access each document via its ID? You can just make an HTTP GET request to (assuming CouchDb is run locally):
GET localhost:5984/<database>/<id>
That will return the entire document
Based on your comment below, the best way to get each item in the document is to create a map view in Couch. Say your document looks like this:
{
_id: 123,
rev: 22,
posts: [{ id: 2, name: hello}, {id: 3, name: world}]
}
If you wanted to list all of the posts, your Map view would look like this:
function(doc){
for(var post in doc.posts){
emit([doc._id, post], 1);
}
}
That will emit all of the posts in every single document. If you have different types of documents, you can add code to only emit for certain types of documents. Then you can go to the URL for the view to see all of the posts: http://localhost:5984/database/_design/ViewCategory/_view/ViewName?reduce=false

Meteor Querying other users by email

I'm trying to query users by emails with the following command
Meteor.users.findOne({'emails.address': 'me#example.com'});
It works in the mongo shell but it returns undefined in Meteor.
Any ideas?
UPDATE
Turned out that I'm not able to query other users. The same query works when I query the logged in user email.
So the question now how can I query on all the users?
By default, Meteor only publishes the logged in user and you can, as you mention, run queries against that user. In order to access the other users you have to publish them on the server:
Meteor.publish("allUsers", function () {
return Meteor.users.find({});
});
And subscribe to them on the client:
Meteor.subscribe('allUsers');
Also keep in mind that you might not want to publish all the fields so you can specify what fields you like to publish/not publish:
return Meteor.users.find({},
{
// specific fields to return
'profile.email': 1,
'profile.name': 1,
'profile.createdAt': 1
});
Once you have published the collection, you can run queries and access information for all the users.
This may be helpful:
var text = "me#example.com";
Meteor.users.findOne({'emails.address': {$regex:text,$options:'i'}});
Also see Advance Queries
First you need to publish the users as mentioned above answer and run the following command
Meteor.users.find({"emails": "me#example.com"}).fetch()
OR
Meteor.users.find({"emails.0": "me#example.com"}).fetch()