1
votes

Does two $unwind method acceptable in NodeJS, MongoDb query? I'm trying to get all distinct sub document of two documents.

Here's my query:

col.aggregate([
    {$match: {name: 'Facebook'}},

    {$unwind: "$products"},
    {$unwind: "$offices"},

    {$group:{
        "_id":  {
            CompanyName: "$name",
            HomepageURL: "$homepage_url",
            Description: "$description",
            NumberofEmployees: "$number_of_employees",
            TotalMoneyRaised: "$total_money_raised",
            FoundedYear: "$founded_year",
            CompanyCategory:{ $cond: { if: { $gte: [ "$number_of_employees", 10000 ] }, then: "BIG COMPANY", else: "SMALL COMPANY" }}    
                },
            Products: {$push: '$products.name'},             
            Offices: {$push: '$offices.description'}    
            }   
    },

    {$sort:{name: 1}}

]).toArray(function(err, docs) {
    console.log(docs);
    client.close();
});
});

I try to unwind two nested arrays but the query outputs duplicate values. Here's the result for Products and Offices:

Products:
 [ 'Facebook Platform',
   'Facebook Platform',
   'Facebook Platform',
   'Facebook News Feed',
   'Facebook News Feed',
   'Facebook News Feed',
   'Facebook Chat',
   'Facebook Chat',
   'Facebook Chat',
   'Facebook Connect',
   'Facebook Connect',
   'Facebook Connect',
   'Facebook Mobile',
   'Facebook Mobile',
   'Facebook Mobile',
   'Facebook',
   'Facebook',
   'Facebook',
   'Facebook Lite',
   'Facebook Lite',
   'Facebook Lite',
   'Facebook Places',
   'Facebook Places',
   'Facebook Places' ],
Offices:
 [ 'Headquarters',
   'Europe HQ',
   'New York',
   'Headquarters',
   'Europe HQ',
   'New York',
   'Headquarters',
   'Europe HQ',
   'New York',
   'Headquarters',
   'Europe HQ',
   'New York',
   'Headquarters',
   'Europe HQ',
   'New York',
   'Headquarters',
   'Europe HQ',
   'New York',
   'Headquarters',
   'Europe HQ',
   'New York',
   'Headquarters',
   'Europe HQ',
   'New York' ] } ]

Here's my desired result, distinct products and distinct offices:

[ { _id:
 { CompanyName: 'Facebook',
   HomepageURL: 'http://facebook.com',
   Description: 'Social network',
   NumberofEmployees: 5299,
   TotalMoneyRaised: '$2.43B',
   FoundedYear: 2004,
   CompanyCategory: 'SMALL COMPANY' },
Products:
 [ 'Facebook Platform',
   'Facebook News Feed',
   'Facebook Chat',
   'Facebook Connect',
   'Facebook Mobile',
   'Facebook',
   'Facebook Lite',
   'Facebook Places'  ],
Offices:
 [ 'Headquarters',
   'Europe HQ',
   'New York'] } ]

here's the database for reference:

 {
"_id" : ObjectId("52cdef7c4bab8bd675297d8e"),
"name" : "Facebook",
"homepage_url" : "http://facebook.com",
"description" : "Social network",
"number_of_employees" : 5299,
"total_money_raised" : "$2.43B",
"founded_year" : 2004,
"number_of_employees" : 5299,
"products" : [ 
    {
        "name" : "Facebook Platform",
        "permalink" : "facebook-platform"
    }, 
    {
        "name" : "Facebook News Feed",
        "permalink" : "facebook-news-feed"
    }, 
    {
        "name" : "Facebook Chat",
        "permalink" : "facebook-chat"
    }, 
    {
        "name" : "Facebook Connect",
        "permalink" : "facebook-connect"
    }, 
    {
        "name" : "Facebook Mobile",
        "permalink" : "facebook-iphone-app"
    }, 
    {
        "name" : "Facebook",
        "permalink" : "facebook-zero"
    }, 
    {
        "name" : "Facebook Lite",
        "permalink" : "facebook-lite"
    }, 
    {
        "name" : "Facebook Places",
        "permalink" : "facebook-places"
    }
],
"offices" : [ 
    {
        "description" : "Headquarters",
        "address1" : "1601 Willow Road",
        "address2" : "",
        "zip_code" : "94025",
        "city" : "Menlo Park",
        "state_code" : "CA",
        "country_code" : "USA",
        "latitude" : 37.41605,
        "longitude" : -122.151801
    }, 
    {
        "description" : "Europe HQ",
        "address1" : "",
        "address2" : "",
        "zip_code" : "",
        "city" : "Dublin",
        "state_code" : null,
        "country_code" : "IRL",
        "latitude" : 53.344104,
        "longitude" : -6.267494
    }, 
    {
        "description" : "New York",
        "address1" : "340 Madison Ave",
        "address2" : "",
        "zip_code" : "10017",
        "city" : "New York",
        "state_code" : "NY",
        "country_code" : "USA",
        "latitude" : 40.7557162,
        "longitude" : -73.9792469
    }
],

addtoset Query(w/o unwind):

    col.aggregate([
    {$match: {name: 'Facebook'}},

    //{$unwind: "$products"},
    //{$unwind: "$offices"},

    {$group:{
        "_id":  {
            CompanyName: "$name",
            HomepageURL: "$homepage_url",
            Description: "$description",
            NumberofEmployees: "$number_of_employees",
            TotalMoneyRaised: "$total_money_raised",
            FoundedYear: "$founded_year",
            CompanyCategory:{ $cond: { if: { $gte: [ "$number_of_employees", 10000 ] }, then: "BIG COMPANY", else: "SMALL COMPANY" }}    
            },
            Products: {$addtoset: '$products.name'},             
            //Offices: {$push: '$offices.description'}    
            }
    },

    {$sort:{name: 1}}

]).toArray(function(err, docs) {
    console.log(docs);
    client.close();
});

the same goes either with unwind o without, NULL result when using addtoset, push with unwind is working(1 $unwind only)

1
Perhaps you could use $facet to split your pipeline in two branches at an appropriate point. docs.mongodb.com/manual/reference/operator/aggregation/facetGreg
@Greg will try this, thanksJomel Yamon

1 Answers

1
votes

Simply replace your 2 $push in group stage by $addToSet : it will 'push' values only once, without dupicates