Query object within object - mongodb

I'm using passport.js to store my users into my mongodb. A user object looks like this
{
"_id" : ObjectId("54893faf0907a100006341ee"),
"local" : {
"password" : [encrypted password],
"email" : "johnsmith#domain.com"
},
"__v" : 0
}
In a mongodb shell how would I go about listing all the emails? I'm finding it difficult to do this as my data sits two level deep within the object. Cheers!

You can use distinct to get a list of a field's distinct values in the collection, using dot notation to reference the embedded field:
db.users.distinct('local.email')

Related

Regarding querying in cloud firestore

I'm doing some research on cloud firestore using flutter. Currently I'm looking into querying in cloud firestore. I got a basic idea of how to query like say in the screenshot of the database given below :
The 2nd (Some Dumb Shit) and 3rd (Some Good Shit) projects belong to the field "Hardware" ..... So if I want to search a project with respect to its field ..... I'll do something like this :
databaseReference.collection("Projects").where("Field",isEqualTo: "Hardware")
But say if I want to search projects based on the name of the members ( Referring to the screenshot above ..... I need to search of a project where a name "Sarvesh Dalvi" is present inside the "Members" field). How am I supposed to write a query in this case.
Note :
Name ("Sarvesh Dalvi") is present inside this heirarchy :
DocumentID(eg : "Some Dumb Shit") / Array("Members") / Map({Name : __ , MemberRef :__});
Thanks in advance for the help.
Update :
I learned how to access an array by doing something like this :
Future<dynamic> getUserProjectFromDatabase(String username)
{
return databaseReference.collection("Projects").where("Members",arrayContains: {"Name" : username}).getDocuments().then((value){
print(value.documents.length);
value.documents.forEach((element) {print(element.data);});
});
}
But this works if the Map only contains :
{"Name" : username};
But in my case my Map is something like this :
{
"Name" : username,
"MemberRef" : /*Reference to a Document*/
};
[Refer to the screenshot posted above]
I only want to query for the Name inside the map and not the MemberRef...... so how can I query something like :
Future<dynamic> getUserProjectFromDatabase(String username)
{
return databaseReference.collection("Projects").where("Members",arrayContains: {"Name" : username,"MemberRef" : /* can be anything */}).getDocuments().then((value){
print(value.documents.length);
value.documents.forEach((element) {print(element.data);});
});
}
There is no way to query for just the member name in your current data structure.
You have two main options:
If you also know the MemberRef for the member, you can query with array-contains: where('Members', arrayContains: {'Name':'New User','MemberRef':'value of memberref'}). This works because array-contains can check if the array contains the complete value that you specify.
If you don't know the MemberRef subbfield, then you'll need to change your data model to allow the query. I typically recommend creating an additional field with just the member names: MemberNames: ["New User", "Sarvesh Dalvi"]. Then you can use the same array-contains operator, but now on this new field with the simple type: where('MemberNames', arrayContains: 'New User').

MongoDB Find and Modify With GraphQL

I am working on GraphQL mutation and need help here. My document looks like
{
"_id" : ObjectId("5bc02db357146d0c385d4988"),
"item_type" : "CategoryMapping",
"id" : null,
"CategoryGroupName" : "Mystries & Thriller",
"CustomCategory" : [
{
"name" : "Private Investigator",
"MappedBisacs" : [
"investigator",
"Privately owned",
"Secret"
]
},
{
"name" : "Crime Investigator",
"MappedBisacs" : [
"crime investigator",
"crime thriller"
]
}
]
}
UI
Allow user to update MappedBisacs through list of checkbox. So user can add/update or delete list of bisacs.
Problem - When client send GraphQL query like following;
mutation {
CategoryMapping_add(input: {CategoryGroupName: "Mystries & Thriller", CustomCategory: [{name: "Crime Investigator", MappedBisacs: ["investigator", "dafdfdaf", "dafsdf"]}]}) {
clientMutationId
}
}
I need to find Specific custom category and update its bisac array.
I am not sure if I got it, but this more a doubt on MongoDb than on GraphQL itself. First you must find the document that you want (I would use the id of the document instead of CategoryGroupName), then you can update this array in several ways. For example, after you found the document, you could simply access the array content and spread into a new one adding this new data from your mutation, and save this object with the update method. (if you simply want to add new data without removing any)
So, it depends on the case.
Check: https://docs.mongodb.com/manual/reference/operator/update-array/
Hope it helps! :)

Mongo sub-document, good practice or not?

After few months working with Mongo trying to understand if using sub-documents for nested data is good or not, especially in this example:
Assume users collection that each document into it have the following:
{
"_id" : ObjectId("some valid Object ID"),
"userName" : "xxxxx",
"email" : "xxxx#xxxx.xx"
}
Now, in my system there are also rooms (another collection) and i want to save for each user scores per room.
In my mind, to do that i have 2 major options, (1) create new collection call userScores that will hold: userId, roomId, scores fields like i did previously in MySql and other relational DB's (2) create a sub-document into the above user document:
{
"_id" : ObjectId("sdfdfdfdfdf"),
"userName" : "xxxxx",
"email" : "xxxx#xxxx.xx",
"scores": {
"roomIdX": 50,
"roomIdY": 50,
"roomIdZ": 50
}
}
What do you think is better way so later i can handle searches, aggregations and other data queries via the code (mongoose in my case)
Thanks.

Search backward on MongoDb

I have 2 collection.
Collection "users"
{
"_id" : ObjectId("54b00098e0fdb6634b1f54e6"),
"state" : "active",
"backends" : [
DBRef("backends", ObjectId("54b001ebe0fd853df1c93419")),
DBRef("backends", ObjectId("54b00284e0fd853df1c9341b"))
]
}
Collection "backends"
{
"_id" : ObjectId("54b001ebe0fd853df1c93419"),
"state" : "running"
}
I want to get a list of backend of a user where the backend's state is "running".
How can mongodb do this like join two table?
Is it any method to search backward from backend or have function the filter?
I can search like this
db.users.find({"backends.$id" : "distring"})
But what if I want to search the state inside backend object? like.
db.users.find({"backends.$state" : "running"})
But ofcoure it is not working.
MongoDB doesn't support joins so you need to do this in two steps. In the shell:
var ids = db.backends.find({state: 'running'}, {_id: 1}).map(function(backend) {
return backend._id;
});
var users = db.users.find({'backends.$id': {$in: ids}}).toArray();
On a side note, you're probably better off using a plain ObjectId instead of a DBRef for the backends array elements unless the ids in that array can actually refer to docs in multiple collections.

Mongodb - combine data from two collections

I know this has been covered quite a lot on here, however, i'm very new to MongoDB and am struggling with applying answers i've found to my situation.
In short, I have two collections 'total_by_country_and_isrc' which is the output from a MapReduce function and 'asset_report' which contains an asset_id not present in the 'total_by_country_and_isrc' collection or the original raw data collection this was MapReduced from.
An example of the data in 'total_by_country_and_isrc' is:
{ "_id" : { "custom_id" : 4748532, "isrc" : "GBCEJ0100080",
"country" : "AE" }, "value" : 0 }
And an example of the data in the 'asset_report' is:
{ "_id" : ObjectId("51824ef016f3edbb14ef5eae"), "Asset ID" :
"A836656134476364", "Asset Type" : "Web", "Metadata Origination" :
"Unknown", "Custom ID" : "4748532", "ISRC" : "", }
I'd like to end up with the following ('total_by_country_and_isrc_with_asset_id'):
{ "_id" : { "Asset ID" : "A836656134476364", "custom_id" : 4748532,
"isrc" : "GBCEJ0100080", "country" : "AE" }, "value" : 0 }
I know how I would approach with in a relational database but I really want to try and get this working in Mongo as i'm dealing with some pretty large collections and feel Mongo is the right tool for the job.
Can anyone offer some guidance here?
I think you want to use the "reduce" output action: Output to a Collection with an Action. You'll need to regenerate total_by_country_and_isrc, because it doesn't look like asset_report has the fields it needs to generate the keys you already have in total_by_country_and_isrc – so "joining" the data is impossible.
First, write a map method that is capable of generating the same keys from the original collection (used to generate total_by_country_and_isrc) and also from the asset_report collection. Think of these keys as the "join" fields.
Next, map and reduce your original collection to create total_by_country_and_isrc with the correct keys.
Finally, map asset_report with the same method you used to generate total_by_country_and_isrc, but use a reduce function that can be used to reduce the intersection (by key) of this mapped data from asset_report and the data in total_by_country_and_isrc.