2

I have a collection with a structure like this:

 {
    "toystore": 22,
    "toystore_name": "Toystore A",
    "toys": [
      {
        "toy": "buzz",
        "code": 17001,
        "price": 500
      },
      {
        "toy": "woddy",
        "code": 17002,
        "price": 1000
      },
      {
        "toy": "pope",
        "code": 17003,
        "price": 300
      }
    ]
  },
  {
    "toystore": 11,
    "toystore_name": "Toystore B",
    "toys": [
      {
        "toy": "jessie",
        "code": 17005,
        "price": 500
      },
      {
        "toy": "rex",
        "code": 17006,
        "price": 2000
      }
    ]
  }
]

I have n toy stores, and within each toy store I have the toys that this store has available within the toys field (is an array).

There may be repeated codes that I want to search for

[ { "toys.code": 17001 }, { "toys.code": 17003 }, { "toys.code": 17005 }, { "toys.code": 17005 }]

and I want the result to be generated by each of these toys.code no matter if they are repeated, currently the result is not repeated (for example with the code 17005)

this is my current output:

[
      {
        "_id": "Toystore A",
        "toy_array": [
          {
            "price_original": 500,
            "toy": "buzz"
          },
          {
            "price_original": 300,
            "toy": "pope"
          }
        ]
      },
      {
        "_id": "Toystore B",
        "toy_array": [
         //**********
          //as i searched 2 times the code:17005, this object should be shown 2 times. only is showed 1 time. 
          {
            "price_original": 500,
            "toy": "jessie"
          }
        ]
      }
    ]

how can I get a result to return for every match in my array?

this is my live code:

db.collection.aggregate([
      {
        $unwind: "$toys"
      },
      {
        $match: {
          $or: [
            {
              "toys.code": 17001
            },
            {
              "toys.code": 17003
            },
            {
              "toys.code": 17005
            },
            {
              "toys.code": 17005
            }
          ],

        }
      },
      {
        $group: {
          _id: "$toystore_name",
          toy_array: {
            $push: {
              price_original: "$toys.price",
              toy: "$toys.toy"
            },

          },

        },

      },

    ])

https://mongoplayground.net/p/g1-oST015y0

1 Answer 1

1

The $match stage examines each document in the pipeline and evaluates the provided criteria, and either eliminates the document, or passes it along to the next stage. It does not iterate the match criteria and examine the entire stream of documents for each one, which is what needs to happen in order to duplicate the document that is referenced twice.

This can be done, but you will need to pass the array of codes twice in the pipeline, once to eliminate documents that don't match at all, and again to allow the duplication you are looking for.

The stages needed are:

  • $match to eliminate toy store that don't have any of the requested toy
  • $project using
    o $map to iterate the search array
    o $filter to selection matching toys
    o $reduce to eliminate empty arrays, and recombine the entries into a single array
  • an additional $project to remove the codes from toy_array
var codearray = [17001, 17003, 17005, 17005];
db.collection.aggregate([
  {$match: {"toys.code": {$in: codearray }}},
  {$project: {
      _id: "$toystore_name",
      toy_array: {
        $reduce: {
          input: {
            $map: {
              input: codearray,
              as: "qcode",
              in: {
                $filter: {
                  input: "$toys",
                  as: "toy",
                  cond: {$eq: [ "$$toy.code","$$qcode" ]}
                }
              }
            }
          },
          initialValue: [],
          in: {
            $cond: {
              if: {$eq: ["$$this",[]]},
              then: "$$value",
              else: {$concatArrays: ["$$value", "$$this"]}
            }
          }
        }
      }
  }},
  {$project: {"toy_array.code": 0}}
])

Playground

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.