skip to Main Content

I have a Mongoose Schema that looks like this:

{
 _id: ObjectID,
 storage: [{
    location: String,
    storedFood: [{
      code: String,
      name: String,
      weight: Number
    }]
 }]
}

And for example in storedFood can be the same Food twice. But I only want to update one of the weights of these items.
This is my code to $inc all of the items…. How can I reduce this to only one?

try {
    const deletedFoodFromStorage = await User.updateOne(
        {_id: user, "storage.location": location},
        { $inc: {"storage.$.storedFood.$[food].weight": -weight}},
        { arrayFilters: [ { "food.code": code } ]},
    );
    res.json(deletedFoodFromStorage);
} catch(err) {
    res.status(400).json('Error: ' + err)
}

3

Answers


  1. Chosen as BEST ANSWER

    Ty for your help!

    The final solution for me was to restructure addStoredFood-Function to make the storedFood unique and only add weight to it instead of adding another objects.

    This makes my old update-Function work aswell.


  2. Should have been a simple one. Only way I found at the moment is not simple:

    db.collection.update(
      {_id: user, "storage.location": location},
      [
        {$set: {
          newItem: {
            $reduce: {
              input: {$getField: {
                  input: {$first: {$filter: {
                            input: "$storage",
                            as: "st",
                            cond: {$eq: ["$$st.location", location]}
                  }}},
                  field: "storedFood"
              }},
              initialValue: [],
              in: {$concatArrays: [
                  "$$value",
                  {$cond: [
                      {$and: [
                          {$eq: ["$$this.code", code]},
                          {$not: {$in: [code, "$$value.code"]}}
                      ]},
                      [{$mergeObjects: [
                            "$$this",
                            {weight: {$subtract: ["$$this.weight", weight]}}
                      ]}],
                      ["$$this"]
                    ]
                  }
                ]
              }
            }
          }
      }},
      {$set: {
          storage: {
            $map: {
              input: "$storage",
              in: {$cond: [
                  {$eq: ["$$this.location", location]},
                  {$mergeObjects: ["$$this", {storedFood: "$newItem"}]},
                  "$$this"
              ]}
            }
          },
          newItem: "$$REMOVE"
      }}
    ])
    

    See how it works on the playground example

    Login or Signup to reply.
  3. Borrowing liberally from nimrod serok’s answer, here’s one way to do it with a single pass through all the arrays. I suspect this can be improved, at least for clarity.

    db.collection.update({
      _id: user,
      "storage.location": location
    },
    [
      {
        "$set": {
          "storage": {
            "$map": {
              "input": "$storage",
              "as": "store",
              "in": {
                "$cond": [
                  {"$ne": ["$$store.location", location]},
                  "$$store",
                  {
                    "$mergeObjects": [
                      "$$store",
                      {
                        "storedFood": {
                          "$getField": {
                            "field": "theFoods",
                            "input": {
                              "$reduce": {
                                "input": "$$store.storedFood",
                                "initialValue": {
                                  "incOne": false,
                                  "theFoods": []
                                },
                                "in": {
                                  "$cond": [
                                    "$$value.incOne",
                                    {
                                      "incOne": "$$value.incOne",
                                      "theFoods": {
                                        "$concatArrays": [
                                          "$$value.theFoods",
                                          ["$$this"]
                                        ]
                                      }
                                    },
                                    {
                                      "$cond": [
                                        {"$ne": ["$$this.code", code]},
                                        {
                                          "incOne": "$$value.incOne",
                                          "theFoods": {
                                            "$concatArrays": [
                                              "$$value.theFoods",
                                              ["$$this"]
                                            ]
                                          }
                                        },
                                        {
                                          "incOne": true,
                                          "theFoods": {
                                            "$concatArrays": [
                                              "$$value.theFoods",
                                              [
                                                {
                                                  "$mergeObjects": [
                                                    "$$this",
                                                    {"weight": {"$add": ["$$this.weight", -weight]}}
                                                  ]
                                                }
                                              ]
                                            ]
                                          }
                                        }
                                      ]
                                    }
                                  ]
                                }
                              }
                            }
                          }
                        }
                      }
                    ]
                  }
                ]
              }
            }
          }
        }
      }
    ])
    

    Try it on mongoplayground.net.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search