小编Ste*_*ter的帖子

MongoDB 聚合 $sample 非常慢

有很多方法可以从 mongodb 集合中选择随机文档(如本答案中所述)。评论指出,如果 mongodb 版本 >= 3.2,则$sample首选在聚合框架中使用。然而,在包含许多小文档的集合上,这似乎非常慢。

下面的代码使用mongoengine来模拟该问题并与“skip random”方法进行比较:

import timeit
from random import randint

import mongoengine as mdb

mdb.connect("test-agg")


class ACollection(mdb.Document):
    name = mdb.StringField(unique=True)

    meta = {'indexes': ['name']}


ACollection.drop_collection()

ACollection.objects.insert([ACollection(name="Document {}".format(n)) for n in range(50000)])


def agg():
    doc = list(ACollection.objects.aggregate({"$sample": {'size': 1}}))[0]
    print(doc['name'])

def skip_random():
    n = ACollection.objects.count()
    doc = ACollection.objects.skip(randint(1, n)).limit(1)[0]
    print(doc['name'])


if __name__ == '__main__':
    print("agg took {:2.2f}s".format(timeit.timeit(agg, number=1)))
    print("skip_random took {:2.2f}s".format(timeit.timeit(skip_random, number=1)))
Run Code Online (Sandbox Code Playgroud)

结果是:

Document 44551
agg took 21.89s
Document 25800
skip_random took …
Run Code Online (Sandbox Code Playgroud)

mongodb pymongo mongoengine

6
推荐指数
1
解决办法
5330
查看次数

Mongoengine update_one + upsert与弃用的get_or_create

假设我有一组使用MongoEngine定义的文档:

class Project(Document):
    name = StringField(required=True)
    client = StringField(required=True)
    code = StringField(required=True,unique=True)
    created = DateTimeField(required=True,default=datetime.datetime.now)
Run Code Online (Sandbox Code Playgroud)

从历史上看,我可以使用该get_or_create方法执行"插入或更新"类型的操作.例如:

Project.objects().get_or_create(name="Test Project One",
                                client="Client One",
                                code="CL1-001")
Run Code Online (Sandbox Code Playgroud)

其中将以下文档添加到集合中:

{
    "name": "Test Project One",
    "client": "Client One",
    "code": "CL1-001",
    "created": {
        "$date": "2014-07-14T14:00:38.024Z"
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,这种方法现在已经贬值建议的替代方法是使用update_one具有upsert=True如下:

Project.objects(code="CL1-002").update_one(set__name="Test Project Two",
                                           set__client="Client One",
                                           upsert=True)
Run Code Online (Sandbox Code Playgroud)

但这导致文档被添加到集合中而没有created字段:

{
    "client": "Client One",
    "code": "CL1-002",
    "name": "Test Project Two"
}
Run Code Online (Sandbox Code Playgroud)

是否有任何方法可以在get_or_create没有竞争条件的情况下使用MongoEngine 复制默认字段行为?

python mongodb mongoengine

5
推荐指数
1
解决办法
3405
查看次数

标签 统计

mongodb ×2

mongoengine ×2

pymongo ×1

python ×1