मैं दस्तावेज़ रूट के साथ-साथ नेस्टेड सरणी के अंदर एक मान बढ़ाना चाहता हूं।

यहां एक खेल का मैदान उदाहरण

स्कीमा

const UserPoints = new Schema(
    {
        points: {
            type: Number,
        },
        monthly: {
            type: [
                new Schema(
                    {
                        year: {
                            type: Number,
                        },
                        month: {
                            type: Number,
                        },
                        points: {
                            type: Number,
                            min: 0,
                        },
                    },
                    {
                        _id: false,
                        timestamps: false,
                    }
                ),
            ],
        },
    },
    {
        timestamps: false,
    }
);

मैंने क्या प्रयास किया
वेरिएबल का उपयोग किया गया: (वर्तमान वर्ष = 2021, वर्तमान माह = 7, एडपॉइंट्स = 5)
नोट: हो सकता है कि वर्ष, माह अभी तक दस्तावेज़ में मौजूद न हो, इसलिए मुझे इसे "अप्सर्ट" के साथ काम करने की आवश्यकता है।

UserPoints.findOneAndUpdate(
    {
        _id: userId,
        "monthly.year": currentYear,
        "monthly.month": currentMonth,
    },
    {
        $inc: {
            points: addPoints,
            "monthly.$.points": addPoints,
        },
    },
    {
        upsert: true,
        new: true,
    }
).exec()

यह काम नहीं करता। और एक त्रुटि देता है:

{
ok:0
code:2
codeName:"BadValue"
name:"MongoError"
}

मैं सराहना करता हूं अगर कोई मुझे एक ही ऑपरेशन में इन मूल्यों को बढ़ाने के लिए सही दिशा में इंगित कर सकता है।


अपडेट करें: एकमात्र तरीका है कि मैं इसे काम कर सकता हूं, पहले यह जांचने के लिए एक प्रश्न बना रहा है कि "मासिक" सरणी में (वर्ष, महीना) मौजूद है या नहीं। निर्भर करता है कि यह मौजूद है, मैं या तो नए महीने को $ पुश करता हूं, या मौजूदा मूल्यों को $ inc करता हूं।

0
Chique 25 अगस्त 2021, 20:52

2 जवाब

सबसे बढ़िया उत्तर

पाइपलाइन अपडेट तरीका, MongoDB>=4.2
. की आवश्यकता है आप अनुक्रमणिका का उपयोग करके _id द्वारा फ़िल्टर करते हैं, इसलिए यह तेज़ भी होगा।

क्वेरी

यहां टेस्ट कोड
(पुट id=1 अपडेट करेगा (सदस्य बिंदुओं और बाहरी बिंदु फ़ील्ड में अंक जोड़ें), id=2 कुछ नहीं करेगा, id=3 सदस्य को खाली सरणी में सम्मिलित करेगा और अंक अपडेट करेगा, id=4 एक सरणी के साथ अप्सर्ट होगा जिसमें केवल यह सदस्य होता है, और अंक इसके अंक)

मामले (यह $cond में भी चेक किया गया आदेश है)

  • दस्तावेज़ मौजूद नहीं है, सरणी में 1 एकल सदस्य होगा, और मूल बिंदुओं में नए सदस्य बिंदुओं का मान होगा
  • दस्तावेज़ मौजूद है, सदस्य मौजूद नहीं है, मासिक खाली है सदस्य {:year ...} जोड़ता है और रूट पॉइंट फ़ील्ड बढ़ाता है
  • दस्तावेज़ मौजूद है, सदस्य मौजूद है सदस्य और मूल बिंदु फ़ील्ड के अंदर वृद्धि बिंदु
  • दस्तावेज़ मौजूद है, सदस्य मौजूद नहीं है, मासिक खाली नहीं है कुछ भी नहीं है
db.collection.update({
  "_id": 4
},
[
  {
    "$addFields": {
      "isupsert": {
        "$not": [
          {
            "$ne": [
              {
                "$type": "$monthly"
              },
              "missing"
            ]
          }
        ]
      }
    }
  },
  {
    "$addFields": {
      "doc": {
        "$switch": {
          "branches": [
            {
              "case": "$isupsert",
              "then": {
                "_id": "$_id",
                "points": 5,
                "monthly": [
                  {
                    "year": 2021,
                    "month": 7,
                    "points": 5
                  }
                ]
              }
            },
            {
              "case": {
                "$and": [
                  {
                    "$isArray": [
                      "$monthly"
                    ]
                  },
                  {
                    "$eq": [
                      {
                        "$size": "$monthly"
                      },
                      0
                    ]
                  }
                ]
              },
              "then": {
                "_id": "$_id",
                "points": 5,
                "monthly": [
                  {
                    "year": 2021,
                    "month": 7,
                    "points": 5
                  }
                ]
              }
            }
          ],
          "default": {
            "$let": {
              "vars": {
                "found": {
                  "$not": [
                    {
                      "$eq": [
                        {
                          "$size": {
                            "$filter": {
                              "input": "$monthly",
                              "as": "m",
                              "cond": {
                                "$and": [
                                  {
                                    "$eq": [
                                      "$$m.year",
                                      2021
                                    ]
                                  },
                                  {
                                    "$eq": [
                                      "$$m.month",
                                      7
                                    ]
                                  }
                                ]
                              }
                            }
                          }
                        },
                        0
                      ]
                    }
                  ]
                }
              },
              "in": {
                "$cond": [
                  "$$found",
                  {
                    "$mergeObjects": [
                      "$ROOT",
                      {
                        "points": {
                          "$add": [
                            "$points",
                            5
                          ]
                        },
                        "monthly": {
                          "$map": {
                            "input": "$monthly",
                            "as": "m",
                            "in": {
                              "$cond": [
                                {
                                  "$and": [
                                    {
                                      "$eq": [
                                        "$$m.year",
                                        2021
                                      ]
                                    },
                                    {
                                      "$eq": [
                                        "$$m.month",
                                        7
                                      ]
                                    }
                                  ]
                                },
                                {
                                  "$mergeObjects": [
                                    "$$m",
                                    {
                                      "points": {
                                        "$add": [
                                          "$$m.points",
                                          5
                                        ]
                                      }
                                    }
                                  ]
                                },
                                "$$m"
                              ]
                            }
                          }
                        }
                      }
                    ]
                  },
                  "$$ROOT"
                ]
              }
            }
          }
        }
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": "$doc"
    }
  },
  {
    "$unset": [
      "isupsert"
    ]
  }
],
{
  "upsert": true
})
1
Takis _ 26 अगस्त 2021, 02:27

आपको $elemMatch . द्वारा सरणी में खोजना चाहिए

UserPoints.findOneAndUpdate(
    {
        _id: userId,
        "monthly":{$elemMatch:{"year": currentYear}},
        "monthly":{$elemMatch:{"month": currentMonth}}
    },
    {
        $inc: {
            points: addPoints,
            "monthly.$.points": addPoints,
        },
    },
    {
        upsert: true,
        new: true,
    }
).exec()
0
mohammad Naimi 25 अगस्त 2021, 22:13