How MongoDB refs works internally? - database

I am really confused about
' How document of other collection is stored in a document?'.
Does ref just keep the address of the document and populate on demand in O(1) or it stores like a relational DB and search throughout the table to get the relevant document?
e.g We have two collections, User and Posts.
User {
_id: mongoId of User,
name: String,
post: reference of post id
}
Post {
_id: mongoId of Post,
title: String,
body: String
}
Now, Users stores Post in form of a reference. While fetching the document which is posted by a particular user, will it go through all the documents in post and fetch the one which is relevant to us or it just store the direct reference to that document and fetch in O(1).

Related

Trying to design a post system, fan-out to followers, etc -- using Redis

I am aiming to build a scalable infrastructure (for fun) for a user posting system where timelines exist, such as a feed system. Feeds would include posts of a users followings.
Anyways, the current approach is this.
UserA follows UserB
Save the follows relationship in the DB
Create a redis list <userBiD-followers> -> [userAid, ...]
UserB creates a post
Save that post into the DB
Push the <postId> into their Redis list <userId-posts> -> [postId1, postId2, postId3, ...]
Now since UserA has a feed redis list <userAid-feed> -> [postId1, postId2, ...]
I essentially iterate over UserB followings, and push UserBs new post into all of their timelines. (fan-out)
Is this the right approach? Anything better I can do?
Another question of mine is, is it much faster to retrieve a redis list of postIds, and pass them into Prisma to get the actual posts than doing queries with just Prisma?
Example below.
const redisUserPosts = redis.lrange(`${userId}-posts`, 0, -1) = ['1', '2', ...]
posts.findMany({
where: {
id: {
in: redisUserPosts
}
}
})
The alternative would be to find by user, do potential other joins, etc, rather than knowing the exact postId which belongs to a user.
I am simply asking for advice on design, this is already implemented.

MongoDB comparison

I am trying to retrieve data in my MongoDB database. If I have the following below in my mongoDB database, I want to select the Password given the Username. So in this case, I will be looking through the database for a Username that is 'e' and retrieving the password associated with that specific Username. I've tried looking everywhere but I can't seem to find a solution on how to do it. I am using express, node, and mongoDB for this personal project. What I have so far is just looking up with database with .find({ Username: Username} and it outputs the entire JSON object.
To clarify, I will be sending a request with a Username of value 'e' and looking it up the database trying to retrieve the value of Password.
{
_id: 62d7712e6d6732706b46094e,
Username: 'e',
Password: 'hi',
__v: 0
}
find takes multiple inputs you can give the select statements also in find itself
so the query will be like
db.collectionName.find({username:'e'},{_id:0,password:1})
mongo by default fetch _id all the time by default so you need to specifically mention to not fetch _id thus _id :0
for such scenarios, there are 2 options if username is unique i would suggest to go with findOne rather then find
db.collectionName.findOne({username:'e'}).password
the same will work if you have multiple records with same username but you want only the first record
but if you want data of all the records as array
db.collectionName.find({username:'e'},{_id:0,password:1})..map( function(u) { return u.password; } )

Querying Firestore without Primary Key

I'd like my users to be able to update the slug on the URL, like so:
url.co/username/projectname
I could use the primary key but unfortunately Firestore does not allow any modifcation on assigned uid once set so I created a unique slug field.
Example of structure:
projects: {
P10syfRWpT32fsceMKEm6X332Yt2: {
slug: "majestic-slug",
...
},
K41syfeMKEmpT72fcseMlEm6X337: {
slug: "beautiful-slug",
...
},
}
A way to modify the slug would be to delete and copy the data on a new document, doing this becomes complicated as I have subcollections attached to the document.
I'm aware I can query by document key like so:
var doc = db.collection("projects");
var query = doc.where("slug", "==", "beautiful-slug").limit(1).get();
Here comes the questions.
Wouldn't this be highly impractical as if I have more than +1000 docs in my database, each time I will have to call a project (url.co/username/projectname) wouldn't it cost +1000 reads as it has to query through all the documents? If yes, what would be the correct way?
As stated in this answer on StackOverflow: https://stackoverflow.com/a/49725001/7846567, only the document returned by a query is counted as a read operation.
Now for your special case:
doc.where("slug", "==", "beautiful-slug").limit(1).get();
This will indeed result in a lot of read operations on the Firestore server until it finds the correct document. But by using limit(1) you will only receive a single document, this way only a single read operation is counted against your limits.
Using the where() function is the correct and recommended approach to your problem.

Querying mongoDB document based on Array element

This is one user's notes. I want to query and get only the notes of this use with "activeFlag:1". My query object code is
findAccountObj =
{ _id: objectID(req.body.accountId),
ownerId: req.body.userId,
bookId: req.body.bookId,
"notes.activeFlag": 1 };
But this query returns all the notes, including the ones with "activeFlag:0".
How do I fix this?
If you are on v2.2, use elementmatch operator. v3.2 and above allow aggregation and filter to return a subset of a document.
here is an example Retrieve only the queried element in an object array in MongoDB collection

Is there a built-in function to get all unique values in an array field, across all records?

My schema looks like this:
var ArticleSchema = new Schema({
...
category: [{
type: String,
default: ['general']
}],
...
});
I want to parse through all records and find all unique values for this field across all records. This will be sent to the front-end via being called by service for look-ahead search on tagging articles.
We can iterate through every single record and run go through each array value and do a check, but this would be O(n2).
Is there an existing function or another way that has better performance?
You can use the distinct function to get the unique values across all category array fields of all documents:
Article.distinct('category', function(err, categories) {
// categories is an array of the unique category values
});
Put an index on category for best performance.

Resources