Nodejs mongoose怎么在子文档的array里update或insert?

Nodejs mongoose怎么在子文档的array里update或insert?

{
“__v”: 1,
“_id”: “538f5f0f6195a184108c8bd8”,
“title”: “GameTitle”,
“item”: [{
“_id”: “538f5f0f6195a184108c8bd6”,
“name”: “itemOne”,
“men”: [{
“_id”: “5390cccf0a84f41f37082874”,
“user”: “id22222222”,
“score”: 2000
}, {
“_id”: “2390cccf0a84f41f37082873”,
“user”: “id33333333”,
“score”: 1000
}]
}, {
“_id”: “538f5f0f6195a184108c8bd7”,
“name”: “itemTwo”,
“men”: []
}],
“status”: 1
}
\n```

    var MenSchema = new mongoose.Schema({
    user: 'String',
    score: {
        type: Number,
        default: 0
        }
    });

    var ItemsSchema = new mongoose.Schema({
        name: String 
        ,men: [MenSchema]
    });

    ListsSchema = new mongoose.Schema({
        title: {
            type: String,
            required: true
        }
        ,item: [ItemsSchema]
    });

    var Items = mongoose.model('item', ItemsSchema);
    var Lists = mongoose.model('lists', ListsSchema);
    var Men = mongoose.model('men', MenSchema);
Insert and update:

function commit(sId, sItem, sUser, sIncreaseScore) {
    Lists.findOne({, "_id": sId,
            "item.name": sItem
        }, null, function(err, documents) {
            if (!err) {
                if (documents != null) {
                    Lists.findOne({
                        "_id": sId,
                        "item.name": sItem,
                        "item.men.user": sUser
                    }, null, function(err, subDoc) {
                        if (!err) {
                            if (subDoc != null) {
                                //increase user score
                                //!!!!!!!!!!!!!But subDoc will get all arrays of item.men, so I can't update it correctly
                            } else {
                                //inser new user score
                                var userData = new Men({
                                    user: sUser,
                                    score: sScore
                                });

                                documents.item[0].men.push(userData);
                                documents.save(function(err) {
                                    if (!err) {
                                        ///!!!!!!!!!!!!!!Will come this
                                        console.log("documents error on save!");
                                    } else {
                                        console.log("save documents ok!");
                                    }
                                });
                            }
                        }
                    });
                }
            } else {
                console.log("not find the game item!");
            }
        }
    );
}
\n```
这是一个类似iOS game center分数排行榜的数据库, 一个游戏里有多个item项目, 每个项目有多个玩家的分数数据.
document里包含了subDoc子文档,子文档里又有一个array,怎么找到这个array里的某个值,并对它进行修改?</code></pre>

4 回复

要解决在子文档的数组中进行更新或插入的问题,我们可以使用 Mongoose 提供的 findOneAndUpdate 方法。这种方法可以方便地找到并更新特定的子文档。

示例代码

首先定义 Schema 和 Models:

const mongoose = require('mongoose');
const { Schema } = mongoose;

// 定义 Men 的 Schema
const MenSchema = new Schema({
    user: String,
    score: {
        type: Number,
        default: 0
    }
});

// 定义 Item 的 Schema
const ItemsSchema = new Schema({
    name: String,
    men: [MenSchema]
});

// 定义 List 的 Schema
const ListsSchema = new Schema({
    title: {
        type: String,
        required: true
    },
    item: [ItemsSchema]
});

const Men = mongoose.model('men', MenSchema);
const Items = mongoose.model('items', ItemsSchema);
const Lists = mongoose.model('lists', ListsSchema);

// 更新或插入函数
async function commit(listId, itemName, userId, increaseScore) {
    try {
        const list = await Lists.findOne({
            _id: listId,
            'item.name': itemName
        });

        if (!list) {
            console.log("未找到对应的游戏项目");
            return;
        }

        const itemIndex = list.item.findIndex(item => item.name === itemName);
        if (itemIndex === -1) {
            console.log("未找到对应的游戏项目");
            return;
        }

        const menIndex = list.item[itemIndex].men.findIndex(men => men.user === userId);
        if (menIndex !== -1) {
            // 如果用户已经存在,则增加分数
            list.item[itemIndex].men[menIndex].score += increaseScore;
        } else {
            // 如果用户不存在,则插入新记录
            list.item[itemIndex].men.push({
                user: userId,
                score: increaseScore
            });
        }

        await list.save();
        console.log("保存成功!");
    } catch (error) {
        console.error("保存时发生错误:", error);
    }
}

// 调用示例
commit("538f5f0f6195a184108c8bd8", "itemOne", "id11111111", 500)
    .then(() => console.log("更新完成"))
    .catch(error => console.error("更新失败:", error));

解释

  1. 定义 Schema:

    • MenSchema: 定义了每个玩家的分数信息。
    • ItemsSchema: 包含多个玩家分数的数组。
    • ListsSchema: 包含多个项目的数组。
  2. 查找和更新逻辑:

    • 使用 findOne 查找指定的游戏列表及其项目。
    • 确认项目是否存在。
    • 查找用户是否已经在项目中,如果存在则增加分数;如果不存在则插入新用户记录。
    • 最后调用 save 方法保存更改。

通过这种方式,你可以有效地管理和更新嵌套的子文档数组。


先看一楼给的mongodb的文档,最关键的还是你怎么查到你要的数据,再去修改 最主要的是如何去查到你要修改的数据,用$elemMatch,$gt,$lt等等,查到了再说修改就easy了吧

要在 Mongoose 中更新或插入子文档数组中的元素,可以使用 findOneAndUpdate 方法。以下是如何实现的步骤:

  1. 使用 findOneAndUpdate 查找并更新指定的子文档。
  2. 如果子文档不存在,则插入新的子文档。

示例代码如下:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 定义模型
const MenSchema = new Schema({
    user: String,
    score: {
        type: Number,
        default: 0
    }
});

const ItemsSchema = new Schema({
    name: String,
    men: [MenSchema]
});

const ListsSchema = new Schema({
    title: {
        type: String,
        required: true
    },
    item: [ItemsSchema]
});

const Items = mongoose.model('item', ItemsSchema);
const Lists = mongoose.model('lists', ListsSchema);

// 更新或插入方法
async function commit(sId, sItem, sUser, sIncreaseScore) {
    try {
        const result = await Lists.findOneAndUpdate(
            {
                _id: sId,
                'item.name': sItem,
                'item.men.user': sUser
            },
            {
                $inc: { 'item.$.men.$.score': sIncreaseScore }
            },
            { new: true, upsert: true }
        );

        if (!result) {
            console.log("未找到对应的子文档");
            return;
        }

        console.log("更新成功:", result);
    } catch (error) {
        console.error("更新失败:", error);
    }
}

// 调用示例
commit("538f5f0f6195a184108c8bd8", "itemOne", "id22222222", 500)
    .then(() => console.log("操作完成"))
    .catch(console.error);

在这个例子中:

  • findOneAndUpdate 方法用于查找匹配的文档,并更新特定的子文档。
  • upsert: true 表示如果找不到匹配的子文档,则会创建一个新的。
  • $inc 用于增加分数。
  • new: true 表示返回更新后的文档。

这样就可以在子文档的数组中更新或插入数据。

回到顶部