One query to get parent of document with id - mongodb

I have id of person ObjectId("5650e94b2e62c5fbfa0ebdd1"). How get name of its leader with one query?
/* 1 */
{
"_id" : ObjectId("5650e94b2e62c5fbfa0ebdd1"),
"login" : "Todd",
"fullname" : "Eva Bailey",
"leader" : ObjectId("5650e94b2e62c5fbfa0ebdd2"),
"group" : ObjectId("5650e94b2e62c5fbfa0ebdbf")
}
/* 2 */
{
"_id" : ObjectId("5650e94b2e62c5fbfa0ebdd2"),
"login" : "Kennedy",
"fullname" : "Oscar Stokes",
"leader" : null,
"group" : ObjectId("5650e94b2e62c5fbfa0ebdbf")
}

MongoDB is non relational database and does not support joins as opposed to other relational DB which defines relationship through reference keys across tables in database.
Instead of defining references of documents across collections in MongoDB you can utilize embedded document feature of MongoDB.
Embedded documents are easy and fast
Example :
{
"_id" : ObjectId("5650e94b2e62c5fbfa0ebdd1"),
"login" : "Todd",
"fullname" : "Eva Bailey",
"leader" :
{
"name":"Tony Smith"
},
"group" : {
}
}

Related

How to view an object embedded with a document in mongodb

> db.orders.find({})
{ "_id" : ObjectId("5b78b933d62e262ddb055509"), "user_id" : "5b16d96a74be42566844e0b4", "game_id" : "5b11c56c6c71dc44976fba55", "seats" : { "_id" : ObjectId("5b78b933d62e262ddb05550a") }, "__v" : 0 }
{ "_id" : ObjectId("5bb135638625d21c0883fe1d"), "user_id" : "5b16d96a74be42566844e0b4", "game_id" : "5b11c56c6c71dc44976fba61", "seats" : { "_id" : ObjectId("5bb135638625d21c0883fe1e") }, "__v" : 0 }
The above is the output of find command on the orders stored in my Mongo Instance.
seats is an array of objects embedded in the orders schema. How can I view and fetch the array stored in Object seats?
seats is a cross-reference field which contains the ObjectIds to anther collection.
Are you using Mongoose? If so you need to use the populate method to fill in the objects on find etc.

Mongodb Query for $lookup against string id in local & _id in foreign table

Mongodb version: MongoDB shell version v3.6.6
I've data in two collections as follows:
collection event:
{
"_id" : ObjectId("5b52dc2a9f5ac63b61186f45"),
"timestamp" : ISODate("2018-07-21T07:09:30.575Z"),
"UserEvent" : "User disconnected user_id=5b522eda9f5ac65b111c72fb",
"Event" : "User disconnected ",
"UserId" : "5b522eda9f5ac65b111c72fb"
}
collection users:
{
"_id" : ObjectId("5b522eda9f5ac65b111c72fb"),
"name" : "som",
"role" : "1"
}
I need result as :
{
"_id" : ObjectId("5b52dc2a9f5ac63b61186f45"),
"timestamp" : ISODate("2018-07-21T07:09:30.575Z"),
"UserEvent" : "User disconnected user_id=5b522eda9f5ac65b111c72fb",
"Event" : "User disconnected ",
"UserId" : "5b522eda9f5ac65b111c72fb",
"name" : "som"
}
Please note, element name from users collection.
I used $lookup combinations several ways but doesn't yield the result because of _id & string UserId joining issues i believe. I'll be thankful if I can get any help.
basically i want to accomplish a simple join as follows:
Select e.*, u.name
from event e,
users u
where e.UserId = u._id
Note: e.UserId has only string like "5b522eda9f5ac65b111c72fb" but u._id has ObjectId("5b522eda9f5ac65b111c72fb")

Unique key in moongose db

I have the following DB:
{
"_id" : ObjectId("556da79a77f9f7465943ff93"),
"guid" : "a12345",
"update_day" : "12:05:10 02.06.15"
}
{
"_id" : ObjectId("556dc4509a0a6a002f97e972"),
"guid" : "bbbb",
"update_day" : "15:03:10 02.06.15"
"__v" : 0
}
{
"_id" : ObjectId("556dc470e57836242f5519eb"),
"guid" : "bbbb",
"update_day" : "15:03:10 02.06.15"
"__v" : 0
}
{
"_id" : ObjectId("556dc47c7e882d3c2fe9e0fd"),
"guid" : "bbbb",
"update_day" : "15:03:10 02.06.15"
"__v" : 0
}
I want to set the guid to be unique, so no to duplicate is possible (Like primary key in MYSQL). So the DB will look like this:
{
"_id" : ObjectId("556da79a77f9f7465943ff93"),
"guid" : "a12345",
"update_day" : "12:05:10 02.06.15"
}
{
"_id" : ObjectId("556dc4509a0a6a002f97e972"),
"guid" : "bbbb",
"update_day" : "15:03:10 02.06.15"
"__v" : 0
}
and when I will insert another "guid":"bbbb" (with the save command), it will fails.
While declaring schema in mongoose, do this
guid : { type : String, unique : true}
AND if you want mongodb to create the guid on its own (like _id) then do this
guid : { type : String, index : { unique : true} }
First, you have to deal with the current state of your MongoDB collection and delete all the duplicated documents.
One thing is sure : you won't be able to create the unique index with duplicates in your collection and dropDupes is now deprecated since the version 2.7.5 so you can't use it. By the way, it was removed because it was almost impossible to predict which document would be deleted in the process.
Two possible solutions :
Create a new collection. Create the unique index on this new collection and run a batch to copy all the documents from the old collection to the new one and make sure you ignore duplicated key error during the process.
Deal with it in your own collection manually :
make sure you won't insert more duplicated documents in your code,
run a batch on your collection to delete the duplicates (and make sure you keep the good one if they are not completely identical),
then add the unique index.
I would declare my guid like so in mongoose :
guid : { type : String, unique : true}

Filtering Mongo items by multiple fields and subfields

I have the following items in my collection:
> db.test.find().pretty()
{ "_id" : ObjectId("532c471a90bc7707609a3d4f"), "name" : "Alice" }
{
"_id" : ObjectId("532c472490bc7707609a3d50"),
"name" : "Bob",
"partner_type1" : {
"status" : "rejected"
}
}
{
"_id" : ObjectId("532c473e90bc7707609a3d51"),
"name" : "Carol",
"partner_type2" : {
"status" : "accepted"
}
}
{
"_id" : ObjectId("532c475790bc7707609a3d52"),
"name" : "Dave",
"partner_type1" : {
"status" : "pending"
}
}
There are two partner types: partner_type1 and partner_type2. A user cannot be accepted partner in the both of types. But he can be a rejected partner in partner_type1 but accepted in the another, for example.
How can I build Mongo query that fetches the users that can become partners?
When your user can only be accepted in one partner-type, you should turn it around: Have a field accepted_as:"partner_type1" or accepted_as:"partner_type2". For people who aren't accepted yet, either have no such field or set it to null.
In both cases, your query to get any non-accepted will then be:
{
data.accepted_as: null
}
(null matches both non-existing fields as well as fields explicitly set to null)
For me the logical schema would be this:
"partner : {
"type": 1,
"status" : "rejected"
}
At least that keeps the paths consistent between documents.
So if you want to stay away from using mapReduce type methods to find out "which field" it is on, and otherwise use plain queries and the aggregation pipeline, then don't vary field paths on documents. If you alter the "data" then that is the most consistent form.

mongodb get elements which was inserted after some document

I have a document and I need to query mongodb database to return me all the documents which was inserted after current document.
Is it possible and how to do that query?
If you do not override the default _id field you can use that objectID (see the mongodb docs) to make a comparison by time. For instance, the following query will find all the documents that are inserted after curDoc has been inserted (assuming none overwrite the _id field):
>db.test.find({ _id : {$gt : curDoc._id}})
Note that these timestamps are not super granular, if you would like a finer grained view of the time that documents are inserted I encourage you to add your own timestamp field to the documents you are inserting and use that field to make such queries.
If you are using Insert time stamp as on of the parameter, you can query like below
> db.foo.find()
{ "_id" : ObjectId("514bf8bbbe11e483111af213"), "Name" : "abc", "Insert_time" : ISODate("2013-03-22T06:22:51.422Z") }
{ "_id" : ObjectId("514bf8c5be11e483111af214"), "Name" : "xyz", "Insert_time" : ISODate("2013-03-22T06:23:01.310Z") }
{ "_id" : ObjectId("514bf8cebe11e483111af215"), "Name" : "pqr", "Insert_time" : ISODate("2013-03-22T06:23:10.006Z") }
{ "_id" : ObjectId("514bf8eabe11e483111af216"), "Name" : "ijk", "Insert_time" : ISODate("2013-03-22T06:23:38.410Z") }
>
Here my Insert_time corresponds to the document inserted time, and following query will give you the documents after a particular Insert_time,
> db.foo.find({Insert_time:{$gt:ISODate("2013-03-22T06:22:51.422Z")}})
{ "_id" : ObjectId("514bf8c5be11e483111af214"), "Name" : "xyz", "Insert_time" : ISODate("2013-03-22T06:23:01.310Z") }
{ "_id" : ObjectId("514bf8cebe11e483111af215"), "Name" : "pqr", "Insert_time" : ISODate("2013-03-22T06:23:10.006Z") }
{ "_id" : ObjectId("514bf8eabe11e483111af216"), "Name" : "ijk", "Insert_time" : ISODate("2013-03-22T06:23:38.410Z") }
>