Laravel MongoDB - aggregation, ordering query











up vote
1
down vote

favorite
1












I am wondering how could I achieve a specific result.



Starting of
I am using https://github.com/jenssegers/laravel-mongodb



The code sample below is used to get an array of documents that contains my specific slug in the rewards node. And till that point, everything works as intended.



 $array = [
'rewards.slug' => ['$eq' => 'example_slug'],
'expired' => ['$gte' => CarbonCarbon::now()->toDateTimeString()]
];
$models = Master::raw(function ($collection) use (&$array) {
return $collection->find(
$array, ["typeMap" => ['root' => 'array', 'document' => 'array']])
->toArray();
});


My example document



{
"_id": {
"$oid": "5be4464eafad20007245543f"
},
"some_int_value": 100,
"some_string_value": "String",
"rewards": [
{
"slug": "example_slug",
"name": "Example slug",
"quantity": 4,
"estimated": {
"value": 18750
}
},
{
"slug": "example_slug",
"name": "Example slug",
"quantity": 1,
"estimated": {
"value": 100
}
},
{
"slug": "other_example",
"name": "Other slug example",
"quantity": 1,
"estimated": {
"value": 100
}
}
],
"expires": "2018-11-08 20:20:45",
}


Desired result



I would like to implement some more complex query, which would do the following.




  • Retrieve documents that : pseudo select all documents that contain reward "slug": "example_slug", sum the quantity of them, return greater than X quantity documents, order by sum quantity desc

  • and a very similar one to the above select all documents that contain reward "slug": "example_slug", sum estimated.value, return greater than X estimated.value documents, order by sum of estimated.value desc


If you do need more explanation feel free to ask, I feel like I don't even know where to start with this one.



All help is greatly appreciated










share|improve this question




























    up vote
    1
    down vote

    favorite
    1












    I am wondering how could I achieve a specific result.



    Starting of
    I am using https://github.com/jenssegers/laravel-mongodb



    The code sample below is used to get an array of documents that contains my specific slug in the rewards node. And till that point, everything works as intended.



     $array = [
    'rewards.slug' => ['$eq' => 'example_slug'],
    'expired' => ['$gte' => CarbonCarbon::now()->toDateTimeString()]
    ];
    $models = Master::raw(function ($collection) use (&$array) {
    return $collection->find(
    $array, ["typeMap" => ['root' => 'array', 'document' => 'array']])
    ->toArray();
    });


    My example document



    {
    "_id": {
    "$oid": "5be4464eafad20007245543f"
    },
    "some_int_value": 100,
    "some_string_value": "String",
    "rewards": [
    {
    "slug": "example_slug",
    "name": "Example slug",
    "quantity": 4,
    "estimated": {
    "value": 18750
    }
    },
    {
    "slug": "example_slug",
    "name": "Example slug",
    "quantity": 1,
    "estimated": {
    "value": 100
    }
    },
    {
    "slug": "other_example",
    "name": "Other slug example",
    "quantity": 1,
    "estimated": {
    "value": 100
    }
    }
    ],
    "expires": "2018-11-08 20:20:45",
    }


    Desired result



    I would like to implement some more complex query, which would do the following.




    • Retrieve documents that : pseudo select all documents that contain reward "slug": "example_slug", sum the quantity of them, return greater than X quantity documents, order by sum quantity desc

    • and a very similar one to the above select all documents that contain reward "slug": "example_slug", sum estimated.value, return greater than X estimated.value documents, order by sum of estimated.value desc


    If you do need more explanation feel free to ask, I feel like I don't even know where to start with this one.



    All help is greatly appreciated










    share|improve this question


























      up vote
      1
      down vote

      favorite
      1









      up vote
      1
      down vote

      favorite
      1






      1





      I am wondering how could I achieve a specific result.



      Starting of
      I am using https://github.com/jenssegers/laravel-mongodb



      The code sample below is used to get an array of documents that contains my specific slug in the rewards node. And till that point, everything works as intended.



       $array = [
      'rewards.slug' => ['$eq' => 'example_slug'],
      'expired' => ['$gte' => CarbonCarbon::now()->toDateTimeString()]
      ];
      $models = Master::raw(function ($collection) use (&$array) {
      return $collection->find(
      $array, ["typeMap" => ['root' => 'array', 'document' => 'array']])
      ->toArray();
      });


      My example document



      {
      "_id": {
      "$oid": "5be4464eafad20007245543f"
      },
      "some_int_value": 100,
      "some_string_value": "String",
      "rewards": [
      {
      "slug": "example_slug",
      "name": "Example slug",
      "quantity": 4,
      "estimated": {
      "value": 18750
      }
      },
      {
      "slug": "example_slug",
      "name": "Example slug",
      "quantity": 1,
      "estimated": {
      "value": 100
      }
      },
      {
      "slug": "other_example",
      "name": "Other slug example",
      "quantity": 1,
      "estimated": {
      "value": 100
      }
      }
      ],
      "expires": "2018-11-08 20:20:45",
      }


      Desired result



      I would like to implement some more complex query, which would do the following.




      • Retrieve documents that : pseudo select all documents that contain reward "slug": "example_slug", sum the quantity of them, return greater than X quantity documents, order by sum quantity desc

      • and a very similar one to the above select all documents that contain reward "slug": "example_slug", sum estimated.value, return greater than X estimated.value documents, order by sum of estimated.value desc


      If you do need more explanation feel free to ask, I feel like I don't even know where to start with this one.



      All help is greatly appreciated










      share|improve this question















      I am wondering how could I achieve a specific result.



      Starting of
      I am using https://github.com/jenssegers/laravel-mongodb



      The code sample below is used to get an array of documents that contains my specific slug in the rewards node. And till that point, everything works as intended.



       $array = [
      'rewards.slug' => ['$eq' => 'example_slug'],
      'expired' => ['$gte' => CarbonCarbon::now()->toDateTimeString()]
      ];
      $models = Master::raw(function ($collection) use (&$array) {
      return $collection->find(
      $array, ["typeMap" => ['root' => 'array', 'document' => 'array']])
      ->toArray();
      });


      My example document



      {
      "_id": {
      "$oid": "5be4464eafad20007245543f"
      },
      "some_int_value": 100,
      "some_string_value": "String",
      "rewards": [
      {
      "slug": "example_slug",
      "name": "Example slug",
      "quantity": 4,
      "estimated": {
      "value": 18750
      }
      },
      {
      "slug": "example_slug",
      "name": "Example slug",
      "quantity": 1,
      "estimated": {
      "value": 100
      }
      },
      {
      "slug": "other_example",
      "name": "Other slug example",
      "quantity": 1,
      "estimated": {
      "value": 100
      }
      }
      ],
      "expires": "2018-11-08 20:20:45",
      }


      Desired result



      I would like to implement some more complex query, which would do the following.




      • Retrieve documents that : pseudo select all documents that contain reward "slug": "example_slug", sum the quantity of them, return greater than X quantity documents, order by sum quantity desc

      • and a very similar one to the above select all documents that contain reward "slug": "example_slug", sum estimated.value, return greater than X estimated.value documents, order by sum of estimated.value desc


      If you do need more explanation feel free to ask, I feel like I don't even know where to start with this one.



      All help is greatly appreciated







      mongodb laravel laravel-5 aggregation-framework jenssegers-mongodb






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 10 at 22:09









      Veeram

      37.2k33057




      37.2k33057










      asked Nov 8 at 17:54









      Kavvson Empcraft

      117323




      117323
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted
          +150










          You can use below aggregation in 3.6.



          $addFields to create an extra slugcount field to hold the result.



          $filter rewards with slug matching example_slug followed by $sum to sum the quantity field.



          $match with $gt > X - aggregation expression to filter documents where the sum of all matching quantities is greater than X



          $sort slugcount desc and $project with exclusion to remove the slugcount from the final response.



          db.colname.aggregate([
          {"$addFields":{
          "slugcount":
          {"$let":{
          "vars":{
          "mslug":{
          "$filter":{
          "input":"$rewards",
          "cond":{"$eq":["$$this.slug","example_slug"]}
          }
          }
          },
          "in":{"$sum":"$$mslug.quantity"}
          }}
          }},
          {"$match":{"slugcount":{"$gt":X}}},
          {"$sort":{"slugcount":-1}},
          {"$project":{"slugcount":0}}
          ])


          Something like



          ModelName::raw(function ($collection) {
          return $collection->aggregate([
          ['$match' => ['expired' => ['$gte' => CarbonCarbon::now()->toDateTimeString()]]],
          ['$addFields' => [
          'slugcount'
          ['$let' => [
          'vars' => [
          'mslug' => [
          '$filter' => [
          'input' => '$rewards',
          'cond' => ['$eq' => ['$$this.slug','example_slug']]
          ]
          ]
          ],
          'in' => ['$sum' => '$$mslug.quantity']
          ]]
          ]],
          ['$match' => ['slugcount'=> ['$gt' => X]]],
          ['$sort' => ['slugcount' => -1]],
          ['$project' => ['slugcount' => 0]]]);
          });


          You can replace quantity with estimated.value for second aggregation.






          share|improve this answer























          • You want those operators single quoted, yes? Eg '$gt' not "$gt".
            – bishop
            Nov 10 at 22:21








          • 1




            @bishop yes thanks. updated.
            – Veeram
            Nov 10 at 22:24










          • Will take a look on that shortly :)
            – Kavvson Empcraft
            Nov 10 at 22:53










          • I feel like we are missing the '$gte' => CarbonCarbon::now()->toDateTimeString() else it seems right, could you update the answer with that :)
            – Kavvson Empcraft
            Nov 10 at 23:09












          • in 17h I can award the bounty thanks :)
            – Kavvson Empcraft
            Nov 11 at 0:26











          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',
          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%2f53213521%2flaravel-mongodb-aggregation-ordering-query%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








          up vote
          1
          down vote



          accepted
          +150










          You can use below aggregation in 3.6.



          $addFields to create an extra slugcount field to hold the result.



          $filter rewards with slug matching example_slug followed by $sum to sum the quantity field.



          $match with $gt > X - aggregation expression to filter documents where the sum of all matching quantities is greater than X



          $sort slugcount desc and $project with exclusion to remove the slugcount from the final response.



          db.colname.aggregate([
          {"$addFields":{
          "slugcount":
          {"$let":{
          "vars":{
          "mslug":{
          "$filter":{
          "input":"$rewards",
          "cond":{"$eq":["$$this.slug","example_slug"]}
          }
          }
          },
          "in":{"$sum":"$$mslug.quantity"}
          }}
          }},
          {"$match":{"slugcount":{"$gt":X}}},
          {"$sort":{"slugcount":-1}},
          {"$project":{"slugcount":0}}
          ])


          Something like



          ModelName::raw(function ($collection) {
          return $collection->aggregate([
          ['$match' => ['expired' => ['$gte' => CarbonCarbon::now()->toDateTimeString()]]],
          ['$addFields' => [
          'slugcount'
          ['$let' => [
          'vars' => [
          'mslug' => [
          '$filter' => [
          'input' => '$rewards',
          'cond' => ['$eq' => ['$$this.slug','example_slug']]
          ]
          ]
          ],
          'in' => ['$sum' => '$$mslug.quantity']
          ]]
          ]],
          ['$match' => ['slugcount'=> ['$gt' => X]]],
          ['$sort' => ['slugcount' => -1]],
          ['$project' => ['slugcount' => 0]]]);
          });


          You can replace quantity with estimated.value for second aggregation.






          share|improve this answer























          • You want those operators single quoted, yes? Eg '$gt' not "$gt".
            – bishop
            Nov 10 at 22:21








          • 1




            @bishop yes thanks. updated.
            – Veeram
            Nov 10 at 22:24










          • Will take a look on that shortly :)
            – Kavvson Empcraft
            Nov 10 at 22:53










          • I feel like we are missing the '$gte' => CarbonCarbon::now()->toDateTimeString() else it seems right, could you update the answer with that :)
            – Kavvson Empcraft
            Nov 10 at 23:09












          • in 17h I can award the bounty thanks :)
            – Kavvson Empcraft
            Nov 11 at 0:26















          up vote
          1
          down vote



          accepted
          +150










          You can use below aggregation in 3.6.



          $addFields to create an extra slugcount field to hold the result.



          $filter rewards with slug matching example_slug followed by $sum to sum the quantity field.



          $match with $gt > X - aggregation expression to filter documents where the sum of all matching quantities is greater than X



          $sort slugcount desc and $project with exclusion to remove the slugcount from the final response.



          db.colname.aggregate([
          {"$addFields":{
          "slugcount":
          {"$let":{
          "vars":{
          "mslug":{
          "$filter":{
          "input":"$rewards",
          "cond":{"$eq":["$$this.slug","example_slug"]}
          }
          }
          },
          "in":{"$sum":"$$mslug.quantity"}
          }}
          }},
          {"$match":{"slugcount":{"$gt":X}}},
          {"$sort":{"slugcount":-1}},
          {"$project":{"slugcount":0}}
          ])


          Something like



          ModelName::raw(function ($collection) {
          return $collection->aggregate([
          ['$match' => ['expired' => ['$gte' => CarbonCarbon::now()->toDateTimeString()]]],
          ['$addFields' => [
          'slugcount'
          ['$let' => [
          'vars' => [
          'mslug' => [
          '$filter' => [
          'input' => '$rewards',
          'cond' => ['$eq' => ['$$this.slug','example_slug']]
          ]
          ]
          ],
          'in' => ['$sum' => '$$mslug.quantity']
          ]]
          ]],
          ['$match' => ['slugcount'=> ['$gt' => X]]],
          ['$sort' => ['slugcount' => -1]],
          ['$project' => ['slugcount' => 0]]]);
          });


          You can replace quantity with estimated.value for second aggregation.






          share|improve this answer























          • You want those operators single quoted, yes? Eg '$gt' not "$gt".
            – bishop
            Nov 10 at 22:21








          • 1




            @bishop yes thanks. updated.
            – Veeram
            Nov 10 at 22:24










          • Will take a look on that shortly :)
            – Kavvson Empcraft
            Nov 10 at 22:53










          • I feel like we are missing the '$gte' => CarbonCarbon::now()->toDateTimeString() else it seems right, could you update the answer with that :)
            – Kavvson Empcraft
            Nov 10 at 23:09












          • in 17h I can award the bounty thanks :)
            – Kavvson Empcraft
            Nov 11 at 0:26













          up vote
          1
          down vote



          accepted
          +150







          up vote
          1
          down vote



          accepted
          +150




          +150




          You can use below aggregation in 3.6.



          $addFields to create an extra slugcount field to hold the result.



          $filter rewards with slug matching example_slug followed by $sum to sum the quantity field.



          $match with $gt > X - aggregation expression to filter documents where the sum of all matching quantities is greater than X



          $sort slugcount desc and $project with exclusion to remove the slugcount from the final response.



          db.colname.aggregate([
          {"$addFields":{
          "slugcount":
          {"$let":{
          "vars":{
          "mslug":{
          "$filter":{
          "input":"$rewards",
          "cond":{"$eq":["$$this.slug","example_slug"]}
          }
          }
          },
          "in":{"$sum":"$$mslug.quantity"}
          }}
          }},
          {"$match":{"slugcount":{"$gt":X}}},
          {"$sort":{"slugcount":-1}},
          {"$project":{"slugcount":0}}
          ])


          Something like



          ModelName::raw(function ($collection) {
          return $collection->aggregate([
          ['$match' => ['expired' => ['$gte' => CarbonCarbon::now()->toDateTimeString()]]],
          ['$addFields' => [
          'slugcount'
          ['$let' => [
          'vars' => [
          'mslug' => [
          '$filter' => [
          'input' => '$rewards',
          'cond' => ['$eq' => ['$$this.slug','example_slug']]
          ]
          ]
          ],
          'in' => ['$sum' => '$$mslug.quantity']
          ]]
          ]],
          ['$match' => ['slugcount'=> ['$gt' => X]]],
          ['$sort' => ['slugcount' => -1]],
          ['$project' => ['slugcount' => 0]]]);
          });


          You can replace quantity with estimated.value for second aggregation.






          share|improve this answer














          You can use below aggregation in 3.6.



          $addFields to create an extra slugcount field to hold the result.



          $filter rewards with slug matching example_slug followed by $sum to sum the quantity field.



          $match with $gt > X - aggregation expression to filter documents where the sum of all matching quantities is greater than X



          $sort slugcount desc and $project with exclusion to remove the slugcount from the final response.



          db.colname.aggregate([
          {"$addFields":{
          "slugcount":
          {"$let":{
          "vars":{
          "mslug":{
          "$filter":{
          "input":"$rewards",
          "cond":{"$eq":["$$this.slug","example_slug"]}
          }
          }
          },
          "in":{"$sum":"$$mslug.quantity"}
          }}
          }},
          {"$match":{"slugcount":{"$gt":X}}},
          {"$sort":{"slugcount":-1}},
          {"$project":{"slugcount":0}}
          ])


          Something like



          ModelName::raw(function ($collection) {
          return $collection->aggregate([
          ['$match' => ['expired' => ['$gte' => CarbonCarbon::now()->toDateTimeString()]]],
          ['$addFields' => [
          'slugcount'
          ['$let' => [
          'vars' => [
          'mslug' => [
          '$filter' => [
          'input' => '$rewards',
          'cond' => ['$eq' => ['$$this.slug','example_slug']]
          ]
          ]
          ],
          'in' => ['$sum' => '$$mslug.quantity']
          ]]
          ]],
          ['$match' => ['slugcount'=> ['$gt' => X]]],
          ['$sort' => ['slugcount' => -1]],
          ['$project' => ['slugcount' => 0]]]);
          });


          You can replace quantity with estimated.value for second aggregation.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 11 at 1:15

























          answered Nov 10 at 22:08









          Veeram

          37.2k33057




          37.2k33057












          • You want those operators single quoted, yes? Eg '$gt' not "$gt".
            – bishop
            Nov 10 at 22:21








          • 1




            @bishop yes thanks. updated.
            – Veeram
            Nov 10 at 22:24










          • Will take a look on that shortly :)
            – Kavvson Empcraft
            Nov 10 at 22:53










          • I feel like we are missing the '$gte' => CarbonCarbon::now()->toDateTimeString() else it seems right, could you update the answer with that :)
            – Kavvson Empcraft
            Nov 10 at 23:09












          • in 17h I can award the bounty thanks :)
            – Kavvson Empcraft
            Nov 11 at 0:26


















          • You want those operators single quoted, yes? Eg '$gt' not "$gt".
            – bishop
            Nov 10 at 22:21








          • 1




            @bishop yes thanks. updated.
            – Veeram
            Nov 10 at 22:24










          • Will take a look on that shortly :)
            – Kavvson Empcraft
            Nov 10 at 22:53










          • I feel like we are missing the '$gte' => CarbonCarbon::now()->toDateTimeString() else it seems right, could you update the answer with that :)
            – Kavvson Empcraft
            Nov 10 at 23:09












          • in 17h I can award the bounty thanks :)
            – Kavvson Empcraft
            Nov 11 at 0:26
















          You want those operators single quoted, yes? Eg '$gt' not "$gt".
          – bishop
          Nov 10 at 22:21






          You want those operators single quoted, yes? Eg '$gt' not "$gt".
          – bishop
          Nov 10 at 22:21






          1




          1




          @bishop yes thanks. updated.
          – Veeram
          Nov 10 at 22:24




          @bishop yes thanks. updated.
          – Veeram
          Nov 10 at 22:24












          Will take a look on that shortly :)
          – Kavvson Empcraft
          Nov 10 at 22:53




          Will take a look on that shortly :)
          – Kavvson Empcraft
          Nov 10 at 22:53












          I feel like we are missing the '$gte' => CarbonCarbon::now()->toDateTimeString() else it seems right, could you update the answer with that :)
          – Kavvson Empcraft
          Nov 10 at 23:09






          I feel like we are missing the '$gte' => CarbonCarbon::now()->toDateTimeString() else it seems right, could you update the answer with that :)
          – Kavvson Empcraft
          Nov 10 at 23:09














          in 17h I can award the bounty thanks :)
          – Kavvson Empcraft
          Nov 11 at 0:26




          in 17h I can award the bounty thanks :)
          – Kavvson Empcraft
          Nov 11 at 0:26


















           

          draft saved


          draft discarded



















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53213521%2flaravel-mongodb-aggregation-ordering-query%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

          Florida Star v. B. J. F.

          Danny Elfman

          Lugert, Oklahoma