mongoose深层修改问题

https://cnodejs.org/topic/50dde64ea7e6c6171a80a678

各位大神好,好久没写点什么东西了,最近也是cnode社区不知道咋的了都登录不进去,今天总算能回到这里,今天遇到这样的一个问题,发出来咨询下各位。 mongoose提供的schema/model/document想必大家都不陌生,model有一个update方法,现假设我的schema如下

//假设Schema对象已经从Mongoose的api中提取出来var schema =newSchema({
    baseinfo:{
        name:String,
        age:Number},
    status:Number});

如果数据库里已经存了这样的数据 {baseinfo:{name:‘loong‘,age:20},status:0} 我现在要做这样的事情,只修改年龄。 我知道model的update方法支持mongodb原生的api,例如

//代码1
    schemaModel.update({name:‘loong‘},{$set:{baseinfo:{age:26}}});

$setapi原本是支持有值覆盖/没值不改这一套模式(我称之为设置模式)的,即**$set后传入什么就修改什么,如果不传世不会被修改了,代码1中我没有传入status的修改,因此执行后在数据库的数据仍然是0。 但问题就来了,$set支持这的这模式对于层级只有一层的status很有用,但是对于有2个层级的baseinfo来说就不是这样的了。代码1最终运行的结果是age确实改为了26,但name属性却没有了。他的理解是将baseinfo:{age:26}这个键值对对应的覆盖(我称之为覆盖模式**)到实体上,理所当然的没有了name咯。 当然我在问问前我肯定是要做一番研究的,我从来不会做那种自己不研究就上来问问题的。那么我要研究的课题是:如何让mongoose的model支持多层级属性设置模式。在上例中,按照我所研究的课题就是,传什么,改什么,对于深层对象也做判断,永远没有覆盖。 于是,我决定采用深层**$set**,看是否能有所效果:

//代码2
    schemaModel.update({name:‘loong‘},{$set:{baseinfo:{$set:{age:26}}}});

这时候,我在baseinfo后,age前又加了个**$set**,因为我觉得**$set**只查找一层,那么设置2个应该就能查找2层咯,但是结果返回错误,这时不被允许的。 再次查找api,尝试了使用如下的方式:

//代码3
    schemaModel.update({name:‘loong‘},{$set:{‘baseinfo.age’:26}});

这时候是可以的,但是问题就来了:1.‘baseinfo.age’这样的写法是需要从json中转换的,麻烦,2.我要更新baseinfo下的多个数据,就要在这里写很多了。 有没有既不需要转换,同时又能解决多个数据的方式呢? 我再次看了看api,尝试了如下的方法:

//代码4
    schemaModel.update({name:‘loong‘},{$set:{‘baseinfo.$’:{age:26}}});

这次代码是通过了,但是貌似并没有实现修改,这我就纳闷了,为什么会这样呢?查看了api,发现,对.$理解错了,他是针对数组的操作,如果有一个数组的匹配项,则做该项的更新。 ok,尝试了很多,发现都没有得到自己想要的结果,那我们就退一步吧,既然model无法实现,那么document能否实现呢?我的尝试仍然继续:

//代码5
    schemaModel.findOne({name:‘loong‘},function(err,doc){
        doc.set({baseinfo:{age:26}});
        doc.save();});

一运行,这次真的成功了,name属性没有消失,而age属性也成功的修改了。 到此实验已经完成,我退而求其次的找到了解决问题的方法。但是我仍然很好奇,希望能有人提供线索帮忙解决以下2个问题: 1.能不能让model也能做到多层次的设置模式,而且要代码简单。 2.代码5如果baseinfo中还有多层的,不知道会不会出现类似代码1的问题,虽然实际中不会设置这么深的层次,但是还是作为一个问题,暂时没时间研究了,希望能有人测一下。

各位大神好,好久没写点什么东西了,最近也是cnode社区不知道咋的了都登录不进去,今天总算能回到这里,今天遇到这样的一个问题,发出来咨询下各位。 mongoose提供的schema/model/document想必大家都不陌生,model有一个update方法,现假设我的schema如下

//假设Schema对象已经从Mongoose的api中提取出来var schema =newSchema({
    baseinfo:{
        name:String,
        age:Number},
    status:Number});

如果数据库里已经存了这样的数据 {baseinfo:{name:‘loong‘,age:20},status:0} 我现在要做这样的事情,只修改年龄。 我知道model的update方法支持mongodb原生的api,例如

//代码1
    schemaModel.update({name:‘loong‘},{$set:{baseinfo:{age:26}}});

$setapi原本是支持有值覆盖/没值不改这一套模式(我称之为设置模式)的,即**$set后传入什么就修改什么,如果不传世不会被修改了,代码1中我没有传入status的修改,因此执行后在数据库的数据仍然是0。 但问题就来了,$set支持这的这模式对于层级只有一层的status很有用,但是对于有2个层级的baseinfo来说就不是这样的了。代码1最终运行的结果是age确实改为了26,但name属性却没有了。他的理解是将baseinfo:{age:26}这个键值对对应的覆盖(我称之为覆盖模式**)到实体上,理所当然的没有了name咯。 当然我在问问前我肯定是要做一番研究的,我从来不会做那种自己不研究就上来问问题的。那么我要研究的课题是:如何让mongoose的model支持多层级属性设置模式。在上例中,按照我所研究的课题就是,传什么,改什么,对于深层对象也做判断,永远没有覆盖。 于是,我决定采用深层**$set**,看是否能有所效果:

//代码2
    schemaModel.update({name:‘loong‘},{$set:{baseinfo:{$set:{age:26}}}});

这时候,我在baseinfo后,age前又加了个**$set**,因为我觉得**$set**只查找一层,那么设置2个应该就能查找2层咯,但是结果返回错误,这时不被允许的。 再次查找api,尝试了使用如下的方式:

//代码3
    schemaModel.update({name:‘loong‘},{$set:{‘baseinfo.age’:26}});

这时候是可以的,但是问题就来了:1.‘baseinfo.age’这样的写法是需要从json中转换的,麻烦,2.我要更新baseinfo下的多个数据,就要在这里写很多了。 有没有既不需要转换,同时又能解决多个数据的方式呢? 我再次看了看api,尝试了如下的方法:

//代码4
    schemaModel.update({name:‘loong‘},{$set:{‘baseinfo.$’:{age:26}}});

这次代码是通过了,但是貌似并没有实现修改,这我就纳闷了,为什么会这样呢?查看了api,发现,对.$理解错了,他是针对数组的操作,如果有一个数组的匹配项,则做该项的更新。 ok,尝试了很多,发现都没有得到自己想要的结果,那我们就退一步吧,既然model无法实现,那么document能否实现呢?我的尝试仍然继续:

//代码5
    schemaModel.findOne({name:‘loong‘},function(err,doc){
        doc.set({baseinfo:{age:26}});
        doc.save();});

一运行,这次真的成功了,name属性没有消失,而age属性也成功的修改了。 到此实验已经完成,我退而求其次的找到了解决问题的方法。但是我仍然很好奇,希望能有人提供线索帮忙解决以下2个问题: 1.能不能让model也能做到多层次的设置模式,而且要代码简单。 2.代码5如果baseinfo中还有多层的,不知道会不会出现类似代码1的问题,虽然实际中不会设置这么深的层次,但是还是作为一个问题,暂时没时间研究了,希望能有人测一下。

6 回复

zs16211楼•3 年前

我觉得model直接改得好处,少了一步save()!但是第二种更自然点,找到这个文件,直接对文件下的key赋值,在保存下,也很简单啊!即使多层,可以一直.下去(数组除外)

schemaModel.findOne({name:‘loong‘},function(err,doc){
        doc.baseinfo.age=26;
        doc.save();});

DoubleSpout2楼•3 年前

你的问题应该是直接对文档里的某一个内嵌文档的属性做修改,而不破坏整个文档吧,我一般用原生的mongo-native,展示给你看下:

[[email protected] ~]# mongoMongoDB shell version:2.2.2
connecting to: test
db.testcol.insert({info:{name:123,age:123,sex:"male"},id:1,weight:0})> db.testcol.find(){"_id":ObjectId("50de94734af5ea426ff2f77b"),"info":{"name":123,"age":123,"sex":"male"},"id":1,"weight":0}> db.testcol.update({id:1},{$set:{"info.name":0}})> db.testcol.find(){"_id":ObjectId("50de94734af5ea426ff2f77b"),"info":{"name":0,"age":123,"sex":"male"},"id":1,"weight":0}

a2721217423楼•3 年前

@snoopy 吴哥的代码形同我的代码3,这个的确是可以,但是问题在于我上面提过的 1.需要将json嵌套转换为字符串.连接格式 2.如果我要更新的数据比较多的时候,就要手动写很多 按照你的例子,如果我要修改name和age,就要

db.testcol.update({id:1},{$set:{"info.name":0,"info.age":25}})//要将前端传过来的json: {info:{name:0,age:25}} 转换为{"info.name":0,"info.age":25}

cony1384楼•3 年前

火钳刘明

ym16235楼•3 年前

var age, data, id, name;

id = req.query.id;

name = req.query.name;

age = req.query.age;

data ={
  name:  name,
  age: age
};

model.findOneAndUpdate({
  _id: id
}, data,null,function(err, results){if(err){return res.json(500, err);}#在此操作代码});

xialvjun6楼•2 年前

用点语法,

//你的代码1
schemaModel.update({name:‘loong‘},{$set:{"baseinfo.age":26}});//字段名加引号保险些,有时候不加引号会有问题,也搞不清楚什么时候有问题

另外再问你个问题啊,那个mongoose链接在整个项目里只可以有一个链接,那如果项目太大,进行数据操作的地方太多,那怎么办,虽然schema什么的都可以在外面定义,但是db.once(“open”,function(){}),所有的数据操作都在回调里,那会很乱的吧。。。有什么比较官方的解决办法吗?

时间: 2024-08-24 22:58:07

mongoose深层修改问题的相关文章

CSDN日报20170401 ——《如果你还是“程序员”,我劝你别创业!》

[程序人生]如果你还是"程序员",我劝你别创业! 作者:北漂周 在IT这一行做得久了,会接触到无数让人哭笑不得的外行话. 「我们就差一个写代码的了」是其中典型的一种,之所以黑它,不是因为程序员有多自大,认为自己被轻视所以愤怒.而是因为说这句话的人里有90%以上绝对不仅仅差一个写代码的,而是一整套技术体系. 那么,程序员在创业公司之中真的这么重要吗??? [数据存储]用 HAWQ 轻松取代传统数据仓库(七) -- 存储分布 作者:wzy0623 在 HAWQ 中创建一个表时,应该预先对数

值得你关注的Android8.0(Android O)上的重要变化

刚适配完Android7.0还没多久,就看到Google官方推出的Android8.0(Android O)的开发者预览版新闻,我的心情你可以好好想想.对于上层应用开发者的我来说,适配新版本的工作还好,而有JNI且有很多深层修改的人来说则是痛苦的.那么这一次的大版本更新,最终何时定型发布?她都带来了哪些新的限制与变化,对我们已有的应用有何影响?新增了什么特性,能否利用起来增加新奇有趣的功能呢? 本文在整理官方的Preview文档同时,运行部分示例代码,为各位一一展现.如果你英文还不错,时间也充裕

为基于 x86 的 Android* 游戏选择合适的引擎

摘要 游戏开发人员知道 Android 中蕴藏着巨大的机遇. 在 Google Play 商店的前 100 款应用中,约一半是游戏应用(在利润最高的前 100 款应用中,它们所占的比例超过 90%). 如要跻身该市场,开发速度非常关键. 一些刚起步的独立开发人员更愿意从零开始来开发自己的所有代码:但是为了达到更高的质量而不用花费数年的时间进行开发,其他人可能会选择已有的游戏引擎. 在选择引擎时,你可以考虑以下几个因素: 成本 - 你计划支出多少费用? 维度 - 你的游戏是二维还是三维? 语言 -

Android研究之为基于 x86 的 Android* 游戏选择合适的引擎详解

摘要 游戏开发人员知道 Android 中蕴藏着巨大的机遇. 在 Google Play 商店的前 100 款应用中,约一半是游戏应用(在利润最高的前 100 款应用中,它们所占的比例超过 90%). 如要跻身该市场,开发速度非常关键. 一些刚起步的独立开发人员更愿意从零开始来开发自己的所有代码:但是为了达到更高的质量而不用花费数年的时间进行开发,其他人可能会选择已有的游戏引擎.上章研究了英特尔 Android* 开发人员指南上的对等应用详解,在选择引擎时,你可以考虑以下几个因素: 成本 - 你

mongoose修改数组中某个特定的值

如果一个文档中有个类型为字符串数组的字段,比如{id:1,tags:['aa','bb','cc']},现在要将tags字段的'bb'改为'BB',之前的办法是这样写的: articleModel.find({tags:{$all:[doc.name]}},function(err,articles){ articles.forEach(function(article){ for(var j = 0;j<article.tags.length;j++){ if(article.tags[j]

mongoose返回值无法修改

mongoose 查询方法 find 例:db.collections.find(query,function(err,doc) { 如果var res = doc[0]  是{name:'feifei'} //假设只有一个元素 //此时你想给这个对象添加一个age属性 res.age = 16; 打印res  发现 没有age这个属性  这是因为doc[0]是一个bson格式的   需要转化为json格式的 转化方式1// var res1 = res.toObject()       res

mongoose 全面理解

一.创建schemas 创建schemas的方式: 1 var userSchema = new mongoose.Schema({ 2 name: String, 3 email: String, 4 createdOn: Date 5 }); schemas中的数据类型有以下几种:? String? Number? Date? Boolean? Buffer? ObjectId? Mixed? Array 特别需要说明一下ObjectId类型和Mixed类型以及Array类型,在schema

Mongoose简单学习笔记

1.1 名词解释 Schema : 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力 Model : 由Schema发布生成的模型,具有抽象属性和行为的数据库操作对 Entity : 由Model创建的实体,他的操作也会影响数据库 注意: 1.本学习文档采用严格命名方式来区别不同对象,例如: var PersonSchema; //Person的文本属性 var PersonModel; //Person的数据库模型 var PersonEntity; //Person实体 2.Sch

Mongoose学习参考文档——基础篇

Mongoose学习参考文档 前言:本学习参考文档仅供参考,如有问题,师请雅正 一.快速通道 1.1 名词解释 Schema : 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力 Model : 由Schema发布生成的模型,具有抽象属性和行为的数据库操作对 Entity : 由Model创建的实体,他的操作也会影响数据库 注意: 1.本学习文档采用严格命名方式来区别不同对象,例如: var PersonSchema; //Person的文本属性 var PersonModel; //