mongodb query to get related data from relational collections - mongodb

I have 6 collections:
A,B,C,D,E and F
the A collection has many relations with B collection:
one side is A collection.
many side is B collection.
collection A with coll_B_list field is connected to collection B.
collection B with coll_A field is connected to collection A.
collection A:
[
{id:"a1", coll_B_list:["b1", "b2", "b3", "b4"]},
{id:"a2", coll_B_list:["b5", "b6", "b7", "b8"]}
]
the B collection has one relation with collections C,D,E and F.
collection B with the coll_C field is connected to collection C.
collection B with the coll_D field is connected to collection D.
collection B with the coll_E field is connected to collection E.
collection B with the coll_F field is connected to collection F.
the collections C, D, E and F with the coll_B field are connected to collection B.
collection B:
[
{id:"b1", date:"2020-06-01", coll_A:"a1", coll_C:"c1", coll_D:"d2"},
{id:"b2", date:"2020-07-01", coll_A:"a1", coll_C:"c2"},
{id:"b3", date:"2020-05-01", coll_A:"a1", coll_C:"c3", coll_D:"d3", coll_E:"e1", coll_F:"f1"},
{id:"b4", date:"2020-08-01", coll_A:"a1", coll_C:"c4", coll_D:"d1", coll_E:"e2"},
{id:"b5", date:"2020-04-01", coll_A:"a2", coll_C:"c5", coll_D:"d4", coll_E:"e3"},
{id:"b6", date:"2020-01-01", coll_A:"a2", coll_C:"c6", coll_D:"d5", coll_E:"e4", coll_F:"f2"},
{id:"b7", date:"2020-10-01", coll_A:"a2", coll_C:"c7"},
{id:"b8", date:"2020-09-01", coll_A:"a2", coll_C:"c8", coll_D:"d6"}
]
collection C:
[
{id:"c1", coll_B:"b1", value:"v1"},
{id:"c2", coll_B:"b2", value:"v2" },
{id:"c3", coll_B:"b3", value:"v3" },
{id:"c4", coll_B:"b4", value:"v4" },
{id:"c5", coll_B:"b5", value:"v5" },
{id:"c6", coll_B:"b6", value:"v6" },
{id:"c7", coll_B:"b7", value:"v7" },
{id:"c8", coll_B:"b8", value:"v8" }
]
collection D:
[
{id:"d1", coll_B:"b4", value:"v9" },
{id:"d2", coll_B:"b1", value:"v10" },
{id:"d3", coll_B:"b3", value:"v11" },
{id:"d4", coll_B:"b5", value:"v12" },
{id:"d5", coll_B:"b6", value:"v13" },
{id:"d6", coll_B:"b8", value:"v14" }
]
collection E:
[
{id:"e1", coll_B:"b3", value:"v15" },
{id:"e2", coll_B:"b4", value:"v16" },
{id:"e3", coll_B:"b5", value:"v17" },
{id:"e4", coll_B:"b6", value:"v18" }
]
collection F:
[
{id:"f1", coll_B:"b3", value:"v19" },
{id:"f2", coll_B:"b6", value:"v20" }
]
I want Query that its result be like this:
coll_B_list field should :
sorted descending base on date field.
in the collections C,D,E and F :
- if exist related collection then show that
- else show the nearest collection
Result:
[
{
id:"a1",
coll_B_list:[
{
id:"b4",
date:"2020-08-01",
coll_C:{id:"c4", value:"v4"},
coll_D:{id:"d1", value:"v9"},
coll_E:{id:"e2", value:"v16"},
coll_F:{id:"f1", value:"v19"} // doesnt exist so get the nearest value
},
{
id:"b2",
date:"2020-07-01",
coll_C:{id:"c2", value:"v2"},
coll_D:{id:"d2", value:"v10"}, // doesnt exist so get the nearest value
coll_E:{id:"e1", value:"v15"}, // doesnt exist so get the nearest value
coll_F:{id:"f1", value:"v19"} // doesnt exist so get the nearest value
},
{
id:"b1",
date:"2020-06-01",
coll_C:{id:"c1", value:"v1"},
coll_D:{id:"d2", value:"v10"},
coll_E:{id:"e1", value:"v15"}, // doesnt exist so get the nearest value
coll_F:{id:"f1", value:"v19"} // doesnt exist so get the nearest value
},
{
id:"b3",
date:"2020-05-01",
coll_C:{id:"c3", value:"v3"},
coll_D:{id:"d3", value:"v11"},
coll_E:{id:"e1", value:"v15"},
coll_F:{id:"f1", value:"v19"} // doesnt exist so get the nearest value
}
]
},
{
id:"a2",
coll_B_list:[
{
id:"b7",
date:"2020-10-01",
coll_C:{id:"c7", value:"v7"},
coll_D:{id:"d6", value:"v14"}, // doesnt exist so get the nearest value
coll_E:{id:"e3", value:"v17"}, // doesnt exist so get the nearest value
coll_F:{id:"f2", value:"v20"} // doesnt exist so get the nearest value
},
{
id:"b8",
date:"2020-09-01",
coll_C:{id:"c8", value:"v8"},
coll_D:{id:"d6", value:"v14"},
coll_E:{id:"e3", value:"v17"}, // doesnt exist so get the nearest value
coll_F:{id:"f2", value:"v20"} // doesnt exist so get the nearest value
},
{
id:"b5",
date:"2020-04-01",
coll_C:{id:"c5", value:"v5"},
coll_D:{id:"d4", value:"v12"},
coll_E:{id:"e3", value:"v17"},
coll_F:{id:"f2", value:"v20"} // doesnt exist so get the nearest value
},
{
id:"b6",
date:"2020-01-01",
coll_C:{id:"c6", value:"v6"},
coll_D:{id:"d5", value:"v13"},
coll_E:{id:"e4", value:"v18"},
coll_F:{id:"f2", value:"v20"}
}
]
}
]
COLLECTIONS IN MONGOPLAYGROUND
NESTED $lookup in MONGOPLAYGROUND
NESTED $lookup in MONGOPLAYGROUND That Sorted

Related

Limit number of items in group().by() in gremlin query

I am trying to run a gremlin query which groups vertices of a certain label into several groups by a certain field (assume it is 'displayName') and limit the number of groups to n and the number of items in each group also to n.
Is there a way to achieve that?
Since group().by() returns a list of the item, I tried using unfold() and then applying limit on the inner items. I managed to limit the number of groups that are returned, but couldn't limit the number of items in each group.
Here's the query I used to limit the number of groups:
g.V().hasLabel('customLabel').group().by('displayName').unfold().limit(n)
// Expected result:(if n == 2)
[
{
"displayName1": [
{ // item 1 in first group
},
{ // item 2 in first group
}
]
},
{
"displayName2": [
{ // item 1 in second group
},
{ // item 2 in second group
}
]
}
]
// Actual result: (when n == 2)
[
{
"displayName1": [
{ // item 1 in first group
},
{ // item 2 in first group
},
... // all the items are included in the result
]
},
{
"displayName2": [
{ // item 1 in second group
},
{ // item 2 in second group
},
... // all the items are included in the result
]
}
]
Currently, with the query above, I get only 2 groups "displayName1" and "displayName2", but each one contains all the items in it and not only 2 as expected.
If you want to limit the answer you can do it by defining the values for each key in the group:
g.V().hasLabel('customLabel')
.group()
.by('displayName')
.by(identity().limit(n).fold())
.unfold().limit(n)

how to write projection query in mongoDB

I have a json object like this.
[{
A:"XXX",
B:"ss",
C:"qee",
Z:[ {e:"p",f:"q",g:"r"},
{e:"w",f:"x",g:"y"},
{e:"s",f:"t",g:"u"}]
},
{
A:"XYX",
B:"ss",
C:"qee",
Z:[ {e:"p",f:"q",g:"r"},
{e:"w",f:"x",g:"y"},
{e:"s",f:"t",g:"u"}]
},
{
A:"YYY",
B:"ss",
C:"qee",
Z:[ {e:"p",f:"q",g:"r"},
{e:"m",f:"n",g:"o"},
{e:"s",f:"t",g:"u"}]
}]
now i want to run a query on basis of A,e,f. and i want resultant object to have A,B,C,Z{} (but for Z, only object that got matched.
so if i give value as {A: "XXX", Z.e:"s", Z.f:"t"} i get
{
A:"XXX",
B:"ss",
C:"qee",
Z:
{e:"s",f:"t",g:"u"}
}
I am not sure how to write projection for this?

How can I add array data to the object if field exist/not exist in mongo db

This is my expected result:
"ForgotPassword": [
{
"UpdatedOn": ISODate("2017-12-06T11:23:23.0Z"),
},
{
"UpdatedOn": ISODate("2017-12-06T11:45:13.0Z"),
}
]
And this what I am getting:
"ForgotPassword": {
"UpdatedOn": [
ISODate("2017-12-20T11:48:15.0Z"),
ISODate("2017-12-20T11:48:30.0Z"),
ISODate("2017-12-21T11:57:21.0Z")
]
}
Actually Forgot password field will not present in the collection document.
When I add the first time it should create Forgotpassword field and inside updatedon should store
And
when I add the second time the inside the Forgotpassword, updatedon should repeat for me it is storing inside updateon
This is my query:
$updateQuery = $queryUpdate->update(
array("CollaboratorId"=>(int)$collaboratorId), //query condition
array('$addToSet'=>array('ForgotPassword.UpdatedOn'=>$currentDate)),
array('upsert'=>1)
);
$queryUpdate->findAndModify(
array("CollaboratorId"=> (int)$collaboratorId),
array('$addToSet'=> array('ForgotPassword' =>array("UpdatedOn" => $currentDate))),
array('new' => 1,"upsert"=>1)
);
With upsert and new and findandmodify and addtoset it is working

Mongodb: assert that all elements in an array have a field not null

Given a collection with documents like this:
Task Collection document
[
{
"_id"=>BSON::ObjectId('54d674b64d42504b6a000000'),
"submissions"=>
[{"_id"=>BSON::ObjectId('54d674b64d42504b6a010000'),
"grade"=>nil,
"user_id"=>BSON::ObjectId('54d1e2454d42503069060000')},
{"_id"=>BSON::ObjectId('54d674b64d42504b6a020000'),
"grade"=>nil,
"user_id"=>BSON::ObjectId('54d1e2454d42503069070000')},
{"_id"=>BSON::ObjectId('54d674b64d42504b6a030000'),
"grade"=>nil,
"user_id"=>BSON::ObjectId('54d1e2454d42503069080000')}
],
},
{
"_id"=>BSON::ObjectId('54d674b64d42504b6a100000'),
"submissions"=>
[{"_id"=>BSON::ObjectId('54d674b64d42504b6a010000'),
"grade"=>5,
"user_id"=>BSON::ObjectId('54d1e2454d42503069060000')},
{"_id"=>BSON::ObjectId('54d674b64d42504b6a020000'),
"grade"=>7,
"user_id"=>BSON::ObjectId('54d1e2454d42503069070000')},
{"_id"=>BSON::ObjectId('54d674b64d42504b6a030000'),
"grade"=>nil,
"user_id"=>BSON::ObjectId('54d1e2454d42503069080000')}
],
},
{
"_id"=>BSON::ObjectId('54d674b64d42509b6a000000'),
"submissions"=>
[{"_id"=>BSON::ObjectId('54d674b64d42504b6a010000'),
"grade"=>8,
"user_id"=>BSON::ObjectId('54d1e2454d42503069060000')},
{"_id"=>BSON::ObjectId('54d674b64d42504b6a020000'),
"grade"=>7,
"user_id"=>BSON::ObjectId('54d1e2454d42503069070000')},
{"_id"=>BSON::ObjectId('54d674b64d42504b6a030000'),
"grade"=>6,
"user_id"=>BSON::ObjectId('54d1e2454d42503069080000')}
],
}
]
How can I get all the tasks documents whose submissions array contains no nil grade?
The result in the example would contain just the last one.
I am using Mongoid, but I welcome a pure Mongodb query too.
Using elem_match and a negative comparison:
Task.where(:submissions.elem_match => { :grade.ne => nil })

Mongodb multikey index

I want to make sure I'm creating the right index for my data structure (documents in mongodb).
My document contains list of items, and each item contain list of locations.
I'm searching for items using it's location, and I want to create the right index for this kind of search.
{ # <- document
"items": [
{ # <- first item
"name": "Item Name",
"locations": [
{ # <- first location
"sw":{"lat":0, "lng":0},
"ne":{"lat":0, "lng":0},
},
{ # <- second location
"sw":{"lat":0, "lng":0},
"ne":{"lat":0, "lng":0},
},
{ # <- more locations...
...
},
]
},
{ # <- second item
...
}
]
}
I'm searching for items using the lat and lng values, and I've used "ensureIndex" with the following key to create the index:
db.<collection>.ensureIndex({"items.locations.sw.lat":1});
db.<collection>.ensureIndex({"items.locations.sw.lng":1});
db.<collection>.ensureIndex({"items.locations.ne.lat":1});
db.<collection>.ensureIndex({"items.locations.ne.lng":1});
Is it the right way?
Thanks