{'aa': 9809, 'bb': 990191}
可以看到,两个conn提交的update_many请求,在mongo内部并不是原子的任务。进程比主线程后起,因此进程在update时,主线程已经执行了部分update任务了。但是由于进程update的documents数量较少,因此很快就追上了主线程的进度,从而只有约10000个record最后是被进程给update的。
在mongo官方的写操作原子性文档中提到,mongodb对于单个document的写操作是原子的。也就是说,在updateMany里,对每一个符合filter的document的修改操作是原子的,但是整个updateMany,不会阻塞其它client的update操作。
如果要多个updateMany任务不发生并发,最简便的第一种方法是在业务逻辑中加锁,或者用一个任务队列进行管理。这种方法不仅适合updateMany场景,同样也适合在update的时候,需要修改表结构的场景(document全量update,可能需要先delete后insert)。
第二种方法是利用mongodb提供的事务功能,使得在单个session上这些updateMany操作能够有序进行。事务功能启用需要mongo为副本集模式,版本至少4.0,若有分布式事务的需求需要至少4.2的版本。
第三种方法则是在每一个documents中加入version字段,在update的filter中去另外对比version版本号,从而保证最新版本的documents能够存入数据库。在这个思路下,也可以另外再加一个meta表存储最新version的信息(每一个doc里还是要version字段)。只有成功更新了meta表的version,才能updateMany数据表中的documents,否则阻止这个意向。
第三种方法相对前两种方法可控性较低,因此实际场景中,暂推荐第一种以及第二种方法。(如果有其它更有效的方法,欢迎指正orz)
在第一种方法的基础上延伸,可以设置一定量的lock,而后将请求信息hash掉,mod进特定idx的lock。这样只需要控制lock的量,就能控制多个updateMany的需求了。
在实际使用mongodb的场景中,我们经常遇到多个请求同时在某个collection里update多条document的需求。这个需求看似有许多种解法,但是具体哪种好也说不准。现在便让我们一探究竟吧~首先我们利用pymongo添加1000000条数据,name字段为hello:from pymongo import MongoClientclient = MongoClient()db ...
线上运行的服务会产生大量的运行及访问日志,日志里会包含一些错误、警告、及用户行为等信息,通常服务会以文本的形式记录日志信息,这样可读性强,方便于日常定位问题,但当产生大量的日志之后,要想从大量日志里挖掘出有价值的内容,则需要对数据进行进一步的存储和分析。本文以存储web服务的访问日志为例,介绍如何使用MongoDB来存储、分析日志数据,让日志数据发挥最大的价值,本文的内容同样使用其他的日志存储型应用。
一个典型的web服务器的访问日志类似如下,包含访问来源、用户、访问的资源地址、访问结果、用户使用的系统及浏览器类型等
myclient = pymongo.MongoClient(host='localhost',port=27017)
mydb = myclient["du_brand"]
mycol = mydb["content"]
mycol2 = mydb["content_new"]
f1 = mycol.find({"color":{"$exists":True}...
MongoTemplate批量更新(支持泛型)
MongoTemplate所有批量操作中,批量添加是最简单的,直接使用mongoTemplate.insert()即可。
// MongoTemplate.class源码中insert方法有支持集合参数的重载函数,并且已经支持泛型
public <T> Collection<T> insert(Collection<? extends T> batchToSave, Class<?> entityClass)
语法是:Article.updateMany({ 查询条件},{要修改的值})
//这里我的实例代码为
Article.updateMany({ username: 123},{username:yuchu}
这里是以username属性为例,当查询条件成立后,修改的属性也可以是ti
集合(collection)
文档(document)
在MongoDB中,数据库和集合都不需要手动创建,当我们创建文档时,如果文档所在的集合或数据库不存在会自动创建数据库和集合
当我们向集合中插入文档时,如果没有给文档指定_id属性,则数据库会自动为文档添加_id,该属性用来作为文档的唯一标识
显示当前的所有数据库show dbs 或 show databases
进入到指定的数据库中use 数据
可以使用 $push 操作符来向嵌套文档中添加一条数据。例如,假设我们有一个名为 "users" 的集合,其中每个文档都包含一个名为 "name" 的字段和一个名为 "addresses" 的嵌套文档数组。要向 "addresses" 数组中添加一条新的地址,可以使用以下命令:
db.users.update(
{ name: "John" },
{ $push: { addresses: { street: "123 Main St", city: "Anytown", state: "CA", zip: "12345" } } }
这将向名为 "John" 的用户文档的 "addresses" 数组中添加一条新的地址。