how to get data in single array in mongodb? - mongodb

I want to achieve my documents in a single array
My data is this:
"summary_data" : [
{
"_id" : ObjectId("60418b730ba57044ec0afddd"),
"category" : "Entertainment",
"name" : "Alia bhatt",
"profession" : "acting"
},
{
"_id" : ObjectId("60418bc838497d42a80879e3"),
"category" : "Entertainment",
"name" : "priyanka chopra",
"profession" : "acting"
},
{
"_id" : ObjectId("60418bef38497d42a80879eb"),
"category" : "Entertainment",
"name" : "radhika apte",
"profession" : "acting"
},
]
}
And i want data like this having min 10(limit) category data of each category.How can achieve this:
"summary_data" : [
{
"_id": ObjectId("60418b730ba57044ec0afddd"),
"data": [{
"Entertainment": [{
"_id": ObjectId("60418ce138497d42a8087a03"),
"category": "Entertainment",
"name": "Alia bhatt",
"profession": "acting"
}],
}]
i have tried many queries some of them are:
db.getCollection('experts').aggregate([
{
$match: {
$or: [
{ category: "Sports" },
{ category: "other" },
{ category: "Entertainment" }
]
}
},
{ $limit: 10 },
{
$group:
{
_id: null,
summary_data: {
$push: {
_id: "$_id",
category: "$category",
name: "$name",
profession: "$profession",
}
},
}
},
])
Please help me to build this query. Thanks in advance.

Related

Get all the records as a list on the basis of group by field in mongo db

As example i have documents like below :
{ "_id" : ObjectId("5ef0f23647c2b4dbae99105c"), "subcategory_name" : "ENTERPRISE ASSET MANAGEMENT", "category_id" : ObjectId("5ef0ec5547c2b4dbae990e9d"), "category_name" : "ERP", "status" : 0 }
{ "_id" : ObjectId("5ef0f23647c2b4dbae991062"), "subcategory_name" : "ENVIRONMENTAL HEALTH AND SAFETY SOFTWARE", "category_id" : ObjectId("5ef0ec5547c2b4dbae990e9d"), "category_name" : "ERP", "status" : 0 }
then i want result like this :
{
"category_id": ObjectId("5ef0ec5547c2b4dbae990e9d"),
"category_name": "ERP",
"subcategory_list": [
{"_id": ObjectId("5ef0f23647c2b4dbae99105c"), "subcategory_name": "ENTERPRISE ASSET MANAGEMENT"},
{"_id": ObjectId("5ef0f23647c2b4dbae991062"), "subcategory_name": "ENVIRONMENTAL HEALTH AND SAFETY SOFTWARE"}
]
}
You can use group to do this
[
{
$group: {
_id: "$category_id",
category_id: {
"$first": "$category_id"
},
category_name: {
$first: "$category_name"
},
subcategory_list: {
$addToSet: {
_id: "$_id",
subcategory_name: "$subcategory_name",
}
}
}
},
{
$project: {
_id: 0
}
}
]
Working Mongo playground

Join two collections by matching value present inside array of object using MongoDB

I want to join two collection using MongoDB but the local filed matching key is present inside array. I am explaining my two document below.
users:
{ "_id" : ObjectId("5ee8c77330e6a86c5e5ce69b"),
"IsDeleted" : false,
"Name" : "savitha",
"Number" : "9848868000",
"Email" : "savitha.k#edqart.com",
"Password" : "savitha1",
"RoleId" : ObjectId("5ee1d885de9b6a5ae2bae165"),
"RoleName" : "KIOSK",
"UserType" : "POS",
"IsActive" : true,
"SalesAgentName" : "",
"salesAgentEmail" : "",
"SalesAgentMobile" : "",
"SalesAgentAlternateMobile" : "",
"SalesAgentRole" : "",
"MerchantID" : "",
"MachineName" : "",
"MachineBank" : "",
"StoreDetails" : [
{
"StoreCode" : "DKAA",
"Counter" : 3,
"TerminalID" : "12345",
"CounterName" : "Counter3"
}
]
}
This is my primary collection and i want to join with below collection.
storeinfo:
{
"_id" : ObjectId("5e447571f034c748ab11bd15"),
"IsActive" : true,
"IsDeleted" : false,
"StoreCode" : "DKAA",
"StoreName" : "Deeksha Group",
"StoreDescription" : "Deeksha Store is a place where Parents can purchase all the school merchandise in one place at reasonable prices.",
"StoreBranch" : "Bengaluru",
}
Here I need to join both collection as per StoreDetails.StoreCode(users) = StoreCode(storeinfo) and then I want to add only StoreName(from storeinfo) with respective record in StoreDetails. I am explaining my query below.
db.getCollection('users').aggregate([
{
$match: {"_id" : ObjectId("5ee8c77330e6a86c5e5ce69b")}
},
{
$addFields: {
"StoreDetails": {
$ifNull : [ "$StoreDetails", [ ] ]
}
}
},
{
$lookup: {
"from": "storeinfo",
"localField": "StoreDetails.StoreCode",
"foreignField": "StoreCode",
"as": "StoreDetails.StoreCode"
}
}
])
But as per this query I am not getting the expected output. My expected output should like below.
{ "_id" : ObjectId("5ee8c77330e6a86c5e5ce69b"),
"IsDeleted" : false,
"Name" : "savitha",
"Number" : "9848868000",
"Email" : "savitha.k#edqart.com",
"Password" : "savitha1",
"RoleId" : ObjectId("5ee1d885de9b6a5ae2bae165"),
"RoleName" : "KIOSK",
"UserType" : "POS",
"IsActive" : true,
"SalesAgentName" : "",
"salesAgentEmail" : "",
"SalesAgentMobile" : "",
"SalesAgentAlternateMobile" : "",
"SalesAgentRole" : "",
"MerchantID" : "",
"MachineName" : "",
"MachineBank" : "",
"StoreDetails" : [
{
"StoreCode" : "DKAA",
"StoreName" : "Deeksha Group"
"Counter" : 3,
"TerminalID" : "12345",
"CounterName" : "Counter3"
}
]
}
Here I need only store Name will add into the respective object as per storecode. But as per my query I am getting all fields value from storeinfo. Can any body help me to resolve this issue.
Here goes the full query
db.users.aggregate([
{
$match: {
"_id": ObjectId("5ee8c77330e6a86c5e5ce69b")
}
},
{
$addFields: {
"StoreDetails": {
$ifNull: [
"$StoreDetails",
[]
]
}
}
},
{
$unwind: "$StoreDetails"
},
{
$lookup: {
"from": "storeinfo",
"localField": "StoreDetails.StoreCode",
"foreignField": "StoreCode",
"as": "StoreDetails.StoreCode"
}
},
{
$unwind: "$StoreDetails.StoreCode"
},
{
$project: {
"Email": 1,
"IsActive": 1,
"IsDeleted": 1,
"MachineBank": 1,
"MachineName": 1,
"MerchantID": 1,
"Name": 1,
"Number": 1,
"Password": 1,
"RoleId": 1,
"RoleName": 1,
"SalesAgentAlternateMobile": 1,
"SalesAgentMobile": 1,
"SalesAgentName": 1,
"SalesAgentRole": 1,
"UserType": 1,
"_id": 1,
"salesAgentEmail": 1,
"StoreDetails": {
"StoreCode": "$StoreDetails.StoreCode.StoreCode",
"Counter": 1,
"CounterName": 1,
"StoreName": "$StoreDetails.StoreCode.StoreName",
"TerminalID": 1
}
}
},
{
$group: {
_id: "$_id",
"Email": {
$first: "$Email"
},
"IsActive": {
$first: "$IsActive"
},
"IsDeleted": {
$first: "$IsDeleted"
},
"MachineBank": {
$first: "$MachineBank"
},
"MachineName": {
$first: "$MachineName"
},
"MerchantID": {
$first: "$MerchantID"
},
"Name": {
$first: "$Name"
},
"Number": {
$first: "$Number"
},
"Password": {
$first: "$Password"
},
"RoleId": {
$first: "$RoleId"
},
"RoleName": {
$first: "$RoleName"
},
"SalesAgentAlternateMobile": {
$first: "$SalesAgentAlternateMobile"
},
"SalesAgentMobile": {
$first: "$SalesAgentMobile"
},
"SalesAgentName": {
$first: "$SalesAgentName"
},
"SalesAgentRole": {
$first: "$SalesAgentRole"
},
"UserType": {
$first: "$UserType"
},
"salesAgentEmail": {
$first: "$salesAgentEmail"
},
"StoreDetails": {
$push: {
StoreCode: "$StoreDetails.StoreCode",
Counter: "$StoreDetails.Counter",
CounterName: "$StoreDetails.CounterName",
StoreName: "$StoreDetails.StoreName",
TerminalID: "$StoreDetails.TerminalID"
}
}
}
}
])
You can see the full working example here:
https://mongoplayground.net/p/6KqECy-o1U8
Thanks

MongoDB Aggregation function

I have the following JSON Documents in Mongo collection named "Movies"
{
"_id": "5ed0c9700b9e8b0e2c542054",
"movie_name": "Jake 123",
"score": 20,
"director": "Jake"
},
{
"_id": "5ed0a9840b9e8b0e2c542053",
"movie_name": "Avatar",
"director": "James Cameroon",
"score": 50,
"boxoffice": [
{
"territory": "US",
"gross": 2000
},
{
"territory": "UK",
"gross": 1000
}
]
},
{
"_id": "5ed0a9630b9e8b0e2c542052",
"movie_name": "Titanic",
"score": 100,
"director": "James Cameroon",
"boxoffice": [
{
"territory": "US",
"gross": 1000
},
{
"territory": "UK",
"gross": 500
}
],
"actors": [
"Kate Winselet",
"Leonardo De Caprio",
"Rajinikanth",
"Kamalhaasan"
]
}
I run the below query which finds the maximum collection of a country of various movies. My intention is to find the maximum collection and the corresponding territory.
db.movies.aggregate([
{$match: {"boxoffice" : { $exists: true, $ne : []}}},
{$project: {
"title":"$movie_name", "max_boxoffice": {$max : "$boxoffice.gross"},
"territory" : "$boxoffice.territory" } }
])
I get the result as follows. How do I get the correct territory that corresponds to the collection?
{
"_id" : ObjectId("5ed0a9630b9e8b0e2c542052"),
"title" : "Titanic",
"max_boxoffice" : 1000,
"territory" : [
"US",
"UK"
]
},
{
"_id" : ObjectId("5ed0a9840b9e8b0e2c542053"),
"title" : "Avatar",
"max_boxoffice" : 2000,
"territory" : [
"US",
"UK"
]
}
Expected output:
Avatar and Titanic has collected more money in US. I wanted territories to display the values of them
{
"_id" : ObjectId("5ed0a9630b9e8b0e2c542052"),
"title" : "Titanic",
"max_boxoffice" : 1000,
"territory" : "US"
},
{
"_id" : ObjectId("5ed0a9840b9e8b0e2c542053"),
"title" : "Avatar",
"max_boxoffice" : 2000,
"territory" : "US"
}
For this specific requirement, you can use $set (aggregation). $set appends new fields to existing documents. and we can include one or more $set stages in an aggregation operation to achieve this like:
db.movies.aggregate([
{
$match: { "boxoffice": { $exists: true, $ne: [] } }
},
{
$set: {
boxoffice: {
$filter: {
input: "$boxoffice",
cond: { $eq: ["$$this.gross", { $max: "$boxoffice.gross" }]}
}
}
}
},
{
$set: {
boxoffice: { $arrayElemAt: ["$boxoffice", 0] }
}
},
{
$project: {
"title": "$movie_name",
"max_boxoffice": "$boxoffice.gross",
"territory": "$boxoffice.territory"
}
}
])
Mongo Playground

MongoDB unwinding 2 embedded arrays separately

I have a question regarding MongoDB aggregation query which is almost similar to $unwind 2 fields separately in mongodb query.
This is the document:
{
"_id" : "1",
"details" : {
"phonenumber" : [
"1",
"2"
],
"name" : [
"a",
"b"
]
}
}
And I am trying to frame a query which will return me the following result:
{ "_id" : "1", "phonenumber" : "1", "name" : null },
{ "_id" : "1", "phonenumber" : "2", "name" : null },
{ "_id" : "1", "phonenumber" : null, "name" : "a" },
{ "_id" : "1", "phonenumber" : null, "name" : "b" }
Could someone please help me with that?
Closest solution I could figure out is by following query:
db.document.aggregate( [ { $unwind: { path: "$details.name"} }, { $unwind: { path: "$details.phonenumber" } }, { $project: { _id: 1, name: "$details.name", phonenumber: "$details.phonenumber" } } ] )
And the output from above query is:
{ "_id" : "1", "phonenumber" : "1", "name" : "a" },
{ "_id" : "1", "phonenumber" : "1", "name" : "b" },
{ "_id" : "1", "phonenumber" : "2", "name" : "a" },
{ "_id" : "1", "phonenumber" : "2", "name" : "b" }
With MongoDB v3.4, one of the possible solution would be,
db.document.aggregate({
'$facet': {
'phonenumber': [{
'$unwind': '$details.phonenumber'
}, {
'$project': {
phonenumber: '$details.phonenumber',
name: null
}
}],
'name': [{
'$unwind': '$details.name'
}, {
'$project': {
name: '$details.name',
phonenumber: null
}
}]
}
}, {
'$project': {
'combined': {
'$setUnion': ['$phonenumber', '$name']
}
}
}, {
'$unwind': '$combined'
}, {
'$replaceRoot': {
'newRoot': '$combined'
}
})
facet allows us to include multiple aggregation pipelines within a single stage, which is available from version 3.4
Alternate solution for earlier versions of mongodb,
db.document.aggregate([{
$unwind: {
path: "$details.name"
}
}, {
$group: {
_id: "$_id",
nameArr: {
$push: {
name: "$details.name",
phonenumber: {
$ifNull: ["$description", null]
}
}
},
"details": {
$first: "$details"
}
}
}, {
$unwind: "$details.phonenumber"
}, {
$group: {
_id: "$_id",
phoneArr: {
$push: {
phonenumber: "$details.phonenumber",
name: {
$ifNull: ["$description", null]
}
}
},
"nameArr": {
$first: "$nameArr"
}
}
}, {
$project: {
_id: 1,
value: {
$setUnion: ["$nameArr", "$phoneArr"]
}
}
}, {
$unwind: "$value"
}, {
$project: {
name: "$value.name",
phonenumber: "$value.phonenumber"
}
}])

Query an ArrayPosition in MongoDB

I have a collection like this:
> db.nodes.find()
{ "_id" : ObjectId("534d44e182bee8420ace927f"), "id" : "59598841", "created_by" : "JOSM", "geo" : { "type" : "Point", "coordinates" : [ 9.7346094, 52.371738 ] } }
{ "_id" : ObjectId("534d44e182bee8420ace9280"), "id" : "59598842", "created_by" : "JOSM", "geo" : { "type" : "Point", "coordinates" : [ 9.7343616, 52.3718121 ] } }
{ "_id" : ObjectId("534d44e182bee8420ace9281"), "id" : "59598845", "created_by" : "JOSM", "geo" : { "type" : "Point", "coordinates" : [ 9.7331504, 52.372057 ] } }
{ "_id" : ObjectId("534d44e182bee8420ace9282"), "id" : "59835778", "created_by" : "JOSM", "geo" : { "type" : "Point", "coordinates" : [ 9.7354137, 52.3711697 ] } }
{ "_id" : ObjectId("534d44e182bee8420ace9283"), "id" : "60409270", "created_by" : "JOSM", "geo" : { "type" : "Point", "coordinates" : [ 9.7354388, 52.3735999 ] } }
Now I want to query the coordinates-array to find the document with the greatest lon-value.
How can I do that, I have no idea :(
Tschüss, Andre
So actually getting the "lon" which is the first value, of the array may not seem immediately apparent, but is quite simple with aggregate:
db.nodes.aggregate([
{ "$project": {
"_id": {
"_id": "$_id",
"id": "$id",
"created_by": "$created_by",
"geo": "$geo",
},
"coordinates": "$geo.coordinates"
}},
{ "$unwind": "$coordinates" },
{ "$group": {
"_id": "$_id",
"lon": { "$first": "$coordinates" }
}},
{ "$sort": { "lon": 1 } },
{ "$limit": 1 },
{ "$project": {
"_id": "$_id._id",
"id": "$_id.id",
"created_by": "$_id.created_by",
"geo": "$_id.geo",
}}
])
Which gives the whole document with the higest value. Or if you just want the value:
db.nodes.aggregate([
{ "$unwind": "$geo.coordinates" },
{ "$group": {
"_id": "$_id",
"lon": { "$first": "$geo.coordinates" }
}},
{ "$group": {
"_id": null,
"lon": { "$max": "$lon" }
}}
])
Try using the aggregation framework
db.nodes.aggregate(
{ $unwind: "geo.coordinate" },
{ $group: { _id: { id: "$id"}, lon: { $first: "geo.coordinate" } } },
{ $group: { _id: null, maxval: { $max: "$lon" } } }
)
For more info on aggregation look here: http://docs.mongodb.org/manual/reference/operator/aggregation/