Updating Embedded Array And Objects In Mongo - mongodb

In Mongo I have a collection of post and each post has comments that are embed with a user id, user name and user email.
- post
- comments
- user_id name email
I was wondering how can I update the all the emails that are associated with a certain id?

Currently, you would have to retrieve comments first, and then update emails.
Depending on which client you use, here is a mongoid example:
comments = post.comments
comments.update_attributes(:email => "a#b.c")
Also there is already a "Use positional operator to update all items in an array" JIRA that, once implemented, will allow you to do it in one shot.

Have you tried the $ positional operator, its the only way to update the matching sub(embedded docs) docs.

Related

Firebase Firestore query by document id using swift

I am trying to query my database to get all the users where the document id is equal to the users id. I know that I can add that id as a field into the document, but I'd like to optimize the memory I take up, so I'd prefer accessing the document id directly through. Something like
.whereField(DOCUMENT_ID, isEqualTo, User.id)
DOCUMENT_ID is not a valid field so far as I know, and I don't know the equivalent. I have read around that other languages modules have a workaround like
.whereField(Firebase.firestore.FieldValues.documentId(), isEqualTo, User.id)
but I've heard hide nor hair of that in swiftUI. Any ideas?
To filter on the document ID in a query, you can use FieldPath.documentID() in Swift too: https://firebase.google.com/docs/reference/swift/firebasefirestore/api/reference/Classes/FieldPath#/c:objc(cs)FIRFieldPath(cm)documentID. But if you do this in a single document, that'd be the same as just doing document(User.id).

Firestore security rules: check if array contains strings different from user's ID

I know how to check if an array contains a given string (as explained for example here). My requirement however is different: I have a document with an array updatedByHistoryArray written at server side that contains the history of the ids of all users who updated such a document, for example [id1, id2, ..., idn].
I would like to allow a delete operation for this document only if the latter has been updated exclusively by the user who wants to delete it.
So, for example, if a user with id24 wants to delete a document, the updatedByHistoryArray of this document has to be [id24, id24, ..., id24].
Is it possible to implement this requirement in the security rules of Firestore?
It sounds possible. Try using hasOnly() to see if the list field contains only a single user ID.
resource.data.updatedByHistoryArray.hasOnly([request.auth.uid])

Document inside document in MongoDB

I am trying to insert multiple objects in one field. Here is the example.
I have a collection of Questions whose fields are Q_ID, Q_Question and Q_ANS.
Now, the user posts a question and it goes into:
Q_ID:1
Q_Question:'this is question'
Now, the other users will post answers.
How can I insert multiple answers, one by one, in Q_ANS? I tried
db.Questions.update({ans:'this is ans'},{$set:{Q_ID:1}})
but it just replaced the previous answer. I want to insert all answers in Q_ANS one by one as they were posted.
You should use $addToSet
db.Questions.update({ans:'this is ans'},{$addToSet:{Q_ID:1}})
If the documents are identicall this will update it.
If you want to add and do not care about duplicates, yu can use $push
db.Questions.update({ans:'this is ans'},{$push:{Q_ID:1}})
Edit:
This links can help you a bit
http://docs.mongodb.org/manual/reference/operator/update/push/
http://docs.mongodb.org/manual/reference/operator/update/addToSet/

how to join a collection and sort it, while limiting results in MongoDB

lets say I have 2 collections wherein each document may look like this:
Collection 1:
target:
_id,
comments:
[
{ _id,
message,
full_name
},
...
]
Collection 2:
user:
_id,
full_name,
username
I am paging through comments via $slice, let's say I take the first 25 entries.
From these entries I need the according usernames, which I receive from the second collection. What I want is to get the comments sorted by their reference username. The problem is I can't add the username to the comments because they may change often and if so, I would need to update all target documents, where the old username was in.
I can only imagine one way to solve this. Read out the entire full_names and query them in the user collection. The result would be sortable but it is not paged and so it takes a lot of resources to do that with large documents.
Is there anything I am missing with this problem?
Thanks in advance
If comments are an embedded array, you will have to do work on the client side to sort the comments array unless you store it in sorted order. Your application requirements for username force you to either read out all of the usernames of the users who commented to do the sort, or to store the username in the comments and have (much) more difficult and expensive updates.
Sorting and pagination don't work unless you can return the documents in sorted order. You should consider a different schema where comments form a separate collection so that you can return them in sorted order and paginate them. Store the username in each comment to facilitate the sort on the MongoDB side. Depending on your application's usage pattern this might work better for you.
It also seems strange to sort on usernames and expect/allow usernames to change frequently. If you could drop these requirements it'd make your life easier :D

mongodb - add column to one collection find based on value in another collection

I have a posts collection which stores posts related info and author information. This is a nested tree.
Then I have a postrating collection which stores which user has rated a particular post up or down.
When a request is made to get a nested tree for a particular post, I also need to return if the current user has voted, and if yes, up or down on each of the post being returned.
In SQL this would be something like "posts.*, postrating.vote from posts join postrating on postID and postrating.memberID=currentUser".
I know MongoDB does not support joins. What are my options with MongoDB?
use map reduce - performance for a simple query?
in the post document store the ratings - BSON size limit?
Get list of all required posts. Get list of all votes by current user. Loop on posts and if user has voted add that to output?
Is there any other way? Can this be done using aggregation?
NOTE: I started on MongoDB last week.
In MongoDB, the simplest way is probably to handle this with application-side logic and not to try this in a single query. There are many ways to structure your data, but here's one possibility:
user_document = {
name : "User1",
postsIhaveLiked : [ "post1", "post2" ... ]
}
post_document = {
postID : "post1",
content : "my awesome blog post"
}
With this structure, you would first query for the user's user_document. Then, for each post returned, you could check if the post's postID is in that user's "postsIhaveLiked" list.
The main idea with this is that you get your data in two steps, not one. This is different from a join, but based on the same underlying idea of using one key (in this case, the postID) to relate two different pieces of data.
In general, try to avoid using map-reduce for performance reasons. And for this simple use case, aggregation is not what you want.