Mongodb更新修改器

1.参考

MongoDB权威指南(第2版)

2.前言

在Mongodb中我们使用的是update方法去更新我们需要更新的文档,比如下面的一个文档结构:

{
    a: 1,
    b: 2,
    c: 3
}

我们想通过update方法来更新里面的键值对a: 1a: 2,或者是只对文档里面的一个键的值进行更改,按照代码所示我们会像下面这样来写代码:

db.test.update({
    a: 1
},{
    a: 2
});

但是真的如我们所示吗?其实结果并不是我们想要的,上面的代码执行后,其实文档更新后的结果为:

{
    a: 2
}

上面的执行代码覆盖了我们整个文档,当然这不是我们想要的结果。如果想要达到我们理想的结果,我们需要使用Mongodb提供的更新修改器(Update Modifier)。

一个键只能存在一个更新修改器

3.$inc修改器

$inc修改器主要是增对指定键的值进行增加值,$inc修改器是能操作数值类型值,这个修改器非常有用。比如下面,通过$inc修改器来计数访问统计。

文档:

{
    title: 'analytics',
    analyticsCount: 1
}

代码:

db.blog.update({
    title: 'analytics'
},{
    $inc: {
        analyticsCount: 1 //这里代表的是给analyticsCount键的值增加1
    }
});

执行代码后文档为:

{
    title: 'analytics',
    analyticsCount: 2
}

4.$set修改器 和 $unset修改器

$set修改器的作用是重写一个键的值,注意这里是重写这个键的值,并不是增加。如果没有这个键则添加并设置值,比如给下面的文档添加一个page键并设置值为’index’。

文档

{
    title: 'analytics',
    analyticsCount: 1
}

代码

db.blog.update({
    title: 'analytics'
}, {
    $set: {
        page: 'index'
    }   
});

执行后的文档

{
    title: 'analytics',
    analyticsCount: 1,
    page: 'index'
}

$unset修改器的作用是删除文档中的一个键值,比如上面的文档我不想要page键值了,那么通过下面代码可以删除page键值,而不影响这个文档中的其他数据

代码

db.blog.update({
    title: 'analytics'
}, {
    $unset: {
        page: 1 //这里意思是删除page键值后面跟着的可以为1也可以为true,表示确认删除
    }
});

5.$setOnInsert修改器

$setOnInsert修改器配合update方法的第三个参数使用upsert

db.test.update({a: 1}, {b: 1}, {upsert: true})

上面的代码执行后会首先会查找是否有a: 1匹配的文档,如果有则替换整个文档内容为b: 1,如果没有则新建一个文档内容为b: 1。而$setOnInsert修改器就是如果遇见没有找到的匹配的文档就新建一个文档并插入后面的值,如果匹配到相应的文档则什么都不做,这个功能相当于设置了一个默认值。

db.test.update({a: 1}, {$setOnInsert: {b: 1}}, {upsert: true})

还需要注意的是update方法默认是只对匹配到的第一个文档执行操作,如果需要对所有匹配到的文档进行操作,那么就需要在第三个参数设置multi的值为true,比如下面这样:

db.test.update({a: 1}, {$setOnInsert: {b: 1}}, {upsert: true, multi: true});

6.数组修改器

6.1.1.$push修改器

$push修改器的作用是向一个键的值为数组类型的值末尾添加数据,如果没有这个键则创建一个,但是如果这个键已经存在了,它的值就必须是数组类型,否则会像下面一样报错:

The field 'page' must be an array but 
is of type bool in document xxxxx

下面的代码是使用$push修改器给文档增加了一个b键,值为一个对象

文档

{
    a: 1
}

代码

db.blog.update({
    a: 1
}, {
    $push: {
        b: {c: 1}
    }
})

执行后的文档

{
    a: 1,
    b: [{c: 1}]
}
6.1.2.$each子修改器

$push一次性只能增加一个数据,如果有大量数据需要写入,每次调用$push修改器那么性能会大大的降低,$each子修改器的出现解决了这个问题,它后面跟一个数组,这个数组的所有值将被依次添加到末尾。

文档

{
    a: 1,
    b: [{c:1}]
}

代码

db.blog.update({
    a: 1
}, {
    $push: {
        pa:{
            $each: [{b:1}, {c:1}, {d:1}]
        }
    }
})

执行后的文档

{
    a: 1,
    b: [{c: 1}, {b:1}, {c:1}, {d:1}]
}
6.1.3.$slice修改器

$slice修改器配合$each能够限制对操作的键值限制能够写入的最大数据,$slice后面跟着一个数字,可以是负数也可以是正数,比如是正数2则取出$each数组中从取出前两个成员重写操作的键的值,负数相反。注意这个方法影响操作键的原始数据。

文档

{
    a: 1,
    b: [{c:1}]
}

代码

db.blog.update({a: 1}, {
        $push: {
          b: {
            $each: [5,6,7,5,4,3],
            $slice: 2
          }
        }
});

执行后的文档

{
    a: 1,
    b: [5, 6]
}
6.1.4.$addToSet修改器

$addToSet修改器可以向数组添加不重复的内容,意思是如果数组中有重复数据,就不在添加。如果$addToSet修改器操作的键不存在,则添加这个键,并且这个键的值为数组,添加的数据为这个数组的成员。

比如下面的代码,执行了两次添加字符串one,执行了一次添加two,在最终的文档中只有两个成员,onetwo

文档

{
    a: 1
}

代码

db.blog.update({a: 1}, {
    $addToSet: {
        c: 'one'
    }
});

db.blog.update({a: 1}, {
    $addToSet: {
        c: 'one'
    }
});

db.blog.update({a: 1}, {
    $addToSet: {
        c: 'two'
    }
});

执行后的文档

{
    a: 1,
    c: ['one']
}
6.1.5.$pop修改器

$pop修改器用于对数组删除成员,对需要删除的键设置为1则把最后一个成员删除,-1则从正序开始删除第一个成员,如果操作一个不存在的键,还是会返回执行成功。

文档

{
    a: 1
    b: [1,2,3]
}

代码

db.blog.update({a: 1}, {
    $pop: {
        b: -1
    }
})

执行结果

{
    a: 1,
    b: [1,2]
}
6.1.6.$pull修改器

$pull修改器用于删除数组中特定的成员,这样很方便我们控制数组里的成员,不用通过循环和索引来删除,比如下面的代码:

文档

{
    a: 1
    b: [1,2,3]
}

代码

db.blog.update({a: 1}, {
    $pull: {
        b: 2
    }
})

执行后的文档

{
    a: 1
    b: [1,3]
}

文完

文档信息

发表评论

电子邮件地址不会被公开。 必填项已用*标注