MongoDB aggregation - filtering sub arrays and projecting part of their data












1















I have documents that look like this one



Each document contains "books" and "movies" but I don't know how many of each.



{ 
"_id" : 1,
"books" : [
{
"title" : "Philosopher's Stone",
"PopularVote" : 10,
"CriticsVote" : 9
},
{
"title" : "Chamber of Secrets",
"PopularVote" : 8,
"CriticsVote" : 6
},
{
"title" : "Prisoner of Azkaban",
"PopularVote" : 2,
"CriticsVote" : 10
}
],
"movies" : [
{
"title" : "Goblet of Fire",
"PopularVote" : 5,
"CriticsVote" : 10
},
{
"title" : "Order of the Phoenix",
"PopularVote" : 8,
"CriticsVote" : 9
}
]
}


I want to select only the arrays that got a 10 on PopularVote OR CriticsVote and project only the title. The result should look like this.



{ 
"_id" : 1,
"books" : [
{
"title" : "Philosopher's Stone",
},
{
"title" : "Prisoner of Azkaban",
}
],
"movies" : [
{
"title" : "Goblet of Fire",
}
]
}


I tried all kind of combinations of $filter and cond: but failed.



Thanks!



p.s. Harry potter fans, this is just a data example that doesn't reflect my opinions on the books and movies (-:










share|improve this question





























    1















    I have documents that look like this one



    Each document contains "books" and "movies" but I don't know how many of each.



    { 
    "_id" : 1,
    "books" : [
    {
    "title" : "Philosopher's Stone",
    "PopularVote" : 10,
    "CriticsVote" : 9
    },
    {
    "title" : "Chamber of Secrets",
    "PopularVote" : 8,
    "CriticsVote" : 6
    },
    {
    "title" : "Prisoner of Azkaban",
    "PopularVote" : 2,
    "CriticsVote" : 10
    }
    ],
    "movies" : [
    {
    "title" : "Goblet of Fire",
    "PopularVote" : 5,
    "CriticsVote" : 10
    },
    {
    "title" : "Order of the Phoenix",
    "PopularVote" : 8,
    "CriticsVote" : 9
    }
    ]
    }


    I want to select only the arrays that got a 10 on PopularVote OR CriticsVote and project only the title. The result should look like this.



    { 
    "_id" : 1,
    "books" : [
    {
    "title" : "Philosopher's Stone",
    },
    {
    "title" : "Prisoner of Azkaban",
    }
    ],
    "movies" : [
    {
    "title" : "Goblet of Fire",
    }
    ]
    }


    I tried all kind of combinations of $filter and cond: but failed.



    Thanks!



    p.s. Harry potter fans, this is just a data example that doesn't reflect my opinions on the books and movies (-:










    share|improve this question



























      1












      1








      1








      I have documents that look like this one



      Each document contains "books" and "movies" but I don't know how many of each.



      { 
      "_id" : 1,
      "books" : [
      {
      "title" : "Philosopher's Stone",
      "PopularVote" : 10,
      "CriticsVote" : 9
      },
      {
      "title" : "Chamber of Secrets",
      "PopularVote" : 8,
      "CriticsVote" : 6
      },
      {
      "title" : "Prisoner of Azkaban",
      "PopularVote" : 2,
      "CriticsVote" : 10
      }
      ],
      "movies" : [
      {
      "title" : "Goblet of Fire",
      "PopularVote" : 5,
      "CriticsVote" : 10
      },
      {
      "title" : "Order of the Phoenix",
      "PopularVote" : 8,
      "CriticsVote" : 9
      }
      ]
      }


      I want to select only the arrays that got a 10 on PopularVote OR CriticsVote and project only the title. The result should look like this.



      { 
      "_id" : 1,
      "books" : [
      {
      "title" : "Philosopher's Stone",
      },
      {
      "title" : "Prisoner of Azkaban",
      }
      ],
      "movies" : [
      {
      "title" : "Goblet of Fire",
      }
      ]
      }


      I tried all kind of combinations of $filter and cond: but failed.



      Thanks!



      p.s. Harry potter fans, this is just a data example that doesn't reflect my opinions on the books and movies (-:










      share|improve this question
















      I have documents that look like this one



      Each document contains "books" and "movies" but I don't know how many of each.



      { 
      "_id" : 1,
      "books" : [
      {
      "title" : "Philosopher's Stone",
      "PopularVote" : 10,
      "CriticsVote" : 9
      },
      {
      "title" : "Chamber of Secrets",
      "PopularVote" : 8,
      "CriticsVote" : 6
      },
      {
      "title" : "Prisoner of Azkaban",
      "PopularVote" : 2,
      "CriticsVote" : 10
      }
      ],
      "movies" : [
      {
      "title" : "Goblet of Fire",
      "PopularVote" : 5,
      "CriticsVote" : 10
      },
      {
      "title" : "Order of the Phoenix",
      "PopularVote" : 8,
      "CriticsVote" : 9
      }
      ]
      }


      I want to select only the arrays that got a 10 on PopularVote OR CriticsVote and project only the title. The result should look like this.



      { 
      "_id" : 1,
      "books" : [
      {
      "title" : "Philosopher's Stone",
      },
      {
      "title" : "Prisoner of Azkaban",
      }
      ],
      "movies" : [
      {
      "title" : "Goblet of Fire",
      }
      ]
      }


      I tried all kind of combinations of $filter and cond: but failed.



      Thanks!



      p.s. Harry potter fans, this is just a data example that doesn't reflect my opinions on the books and movies (-:







      mongodb aggregation-framework






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 1 at 19:42









      mickl

      14.7k51639




      14.7k51639










      asked Jan 1 at 19:36









      Hanan CohenHanan Cohen

      120111




      120111
























          1 Answer
          1






          active

          oldest

          votes


















          1














          Use $addFields with $filter to replace existing books and movies with filtering condition applied and then you can use $project to get only titles, try:



          db.col.aggregate([
          {
          $addFields: {
          books: {
          $filter: {
          input: "$books",
          as: "b",
          cond: {
          $or: [
          { $eq: [ "$$b.PopularVote", 10 ] },
          { $eq: [ "$$b.CriticsVote", 10 ] }
          ]
          }
          }
          },
          movies: {
          $filter: {
          input: "$movies",
          as: "m",
          cond: {
          $or: [
          { $eq: [ "$$m.PopularVote", 10 ] },
          { $eq: [ "$$m.CriticsVote", 10 ] }
          ]
          }
          }
          }
          }
          },
          {
          $project: {
          "books.title": 1,
          "movies.title": 1
          }
          }
          ])





          share|improve this answer

























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53998367%2fmongodb-aggregation-filtering-sub-arrays-and-projecting-part-of-their-data%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            Use $addFields with $filter to replace existing books and movies with filtering condition applied and then you can use $project to get only titles, try:



            db.col.aggregate([
            {
            $addFields: {
            books: {
            $filter: {
            input: "$books",
            as: "b",
            cond: {
            $or: [
            { $eq: [ "$$b.PopularVote", 10 ] },
            { $eq: [ "$$b.CriticsVote", 10 ] }
            ]
            }
            }
            },
            movies: {
            $filter: {
            input: "$movies",
            as: "m",
            cond: {
            $or: [
            { $eq: [ "$$m.PopularVote", 10 ] },
            { $eq: [ "$$m.CriticsVote", 10 ] }
            ]
            }
            }
            }
            }
            },
            {
            $project: {
            "books.title": 1,
            "movies.title": 1
            }
            }
            ])





            share|improve this answer






























              1














              Use $addFields with $filter to replace existing books and movies with filtering condition applied and then you can use $project to get only titles, try:



              db.col.aggregate([
              {
              $addFields: {
              books: {
              $filter: {
              input: "$books",
              as: "b",
              cond: {
              $or: [
              { $eq: [ "$$b.PopularVote", 10 ] },
              { $eq: [ "$$b.CriticsVote", 10 ] }
              ]
              }
              }
              },
              movies: {
              $filter: {
              input: "$movies",
              as: "m",
              cond: {
              $or: [
              { $eq: [ "$$m.PopularVote", 10 ] },
              { $eq: [ "$$m.CriticsVote", 10 ] }
              ]
              }
              }
              }
              }
              },
              {
              $project: {
              "books.title": 1,
              "movies.title": 1
              }
              }
              ])





              share|improve this answer




























                1












                1








                1







                Use $addFields with $filter to replace existing books and movies with filtering condition applied and then you can use $project to get only titles, try:



                db.col.aggregate([
                {
                $addFields: {
                books: {
                $filter: {
                input: "$books",
                as: "b",
                cond: {
                $or: [
                { $eq: [ "$$b.PopularVote", 10 ] },
                { $eq: [ "$$b.CriticsVote", 10 ] }
                ]
                }
                }
                },
                movies: {
                $filter: {
                input: "$movies",
                as: "m",
                cond: {
                $or: [
                { $eq: [ "$$m.PopularVote", 10 ] },
                { $eq: [ "$$m.CriticsVote", 10 ] }
                ]
                }
                }
                }
                }
                },
                {
                $project: {
                "books.title": 1,
                "movies.title": 1
                }
                }
                ])





                share|improve this answer















                Use $addFields with $filter to replace existing books and movies with filtering condition applied and then you can use $project to get only titles, try:



                db.col.aggregate([
                {
                $addFields: {
                books: {
                $filter: {
                input: "$books",
                as: "b",
                cond: {
                $or: [
                { $eq: [ "$$b.PopularVote", 10 ] },
                { $eq: [ "$$b.CriticsVote", 10 ] }
                ]
                }
                }
                },
                movies: {
                $filter: {
                input: "$movies",
                as: "m",
                cond: {
                $or: [
                { $eq: [ "$$m.PopularVote", 10 ] },
                { $eq: [ "$$m.CriticsVote", 10 ] }
                ]
                }
                }
                }
                }
                },
                {
                $project: {
                "books.title": 1,
                "movies.title": 1
                }
                }
                ])






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jan 1 at 20:58









                Hanan Cohen

                120111




                120111










                answered Jan 1 at 19:42









                micklmickl

                14.7k51639




                14.7k51639
































                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53998367%2fmongodb-aggregation-filtering-sub-arrays-and-projecting-part-of-their-data%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

                    Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

                    A Topological Invariant for $pi_3(U(n))$