是否可以在马达中将集合归类?

时间:2019-02-13 06:58:25

标签: python python-3.x mongodb mongodb-motor

因此,我在应用程序中使用Motor,并且希望创建用于与数据库交互的辅助函数,我最初考虑使用MongoTurbine,但我偏向于不使用ORM ,尽管使常规函数更易于调用会很好。

让我们以upsert为例:

我可以使用以下内容写一个upsert:

await collection.update_one({'key': value}, {'set': {'key': value}}, upsert = True)

但是使用起来会更容易:

await collection.upsert({'key': value}, {'set': {'key': value}})

甚至是set方法:

await collection.set({'key': value}, {'key': value})

我有很多这样的方法,还有更多的方法,但是如果有人能指出正确的方向,那就太棒了!

让我问这个问题的触发器是,我发现AsyncIOMotorDatabase中有一个document_class自变量,可用于指定文档的返回类型。但是,没有真正简单的方法来指定自定义集合类。

我知道所有这些都可以使用标准约定来完成,我只是想使事情变得容易,因为有时可能会有一些长的过滤器,更新,投影字典,而我只是在尝试实现自己的约定。

修改

基本上是为了在其中添加更多上下文,我希望创建自定义函数以减少需要一遍又一遍写的字典的数量。以更新用户点为例;我希望能够围绕update_one函数编写一种“包装器”函数,以提高多个模块之间的可读性和可用性。

例如:

async def update_set(key, value, **kwargs):
    self.update_one({key: value}, {'$set': kwargs})

await db.users.update_set('username', 'johndoe', foo = 1, bar = 'test')
#vs
await db.users.update_one({'username': 'johndoe'}, {'$set': {'foo': 1, 'bar': 'batz'}})

2 个答案:

答案 0 :(得分:0)

尽管这不是一个完美的解决方案,但是您可以通过为db对象编写包装器类来实现。在某种程度上,该类扩展了另一个类的对象,而不是该类本身。


db = #get connection 
class Wrapper:
    def __init__(self, obj):
        for key in obj.__dir__():
            # skip internal methods
            if key.startswith("__"):
                continue
            setattr(self, key, getattr(obj, key))

    async def update_set(key, value, **kwargs):
        self.update_one({key: value}, {'$set': kwargs})

db = Wrapper(db)
await db.update_set(...)

注意:

您需要使用包装的对象来访问update_set方法。因此最好在连接时将其包装。

答案 1 :(得分:0)

我尝试了简单的子类化,但没有用:

class MyCollection(motor_asyncio.AsyncIOMotorCollection):
    pass

my_collection = MyCollection(database=db, name='my_collection')

Traceback (most recent call last):
  File "./test.py", line 13, in <module>
    my_collection = MyCollection(database=db, name='my_collection')
  File "/usr/local/lib/python3.6/dist-packages/motor/core.py", line 528, in __init__
    super(self.__class__, self).__init__(delegate)
TypeError: __init__() missing 1 required positional argument: 'name'

但是通过一些技巧,它终于可以工作了:

#!/usr/bin/python3.6

import pymongo
from motor import motor_asyncio


class MyCollection(motor_asyncio.AsyncIOMotorCollection):
    def __init__(self, *args, **kwargs):
        """Calling __init__ of parent class is failing for some reason"""

    def __new__(cls, *args, **kwargs):
        collection = motor_asyncio.AsyncIOMotorCollection(*args, **kwargs)
        collection.__class__ = MyCollection
        return collection

    def my_method(self, *args, **kwargs):
        print('my method', args, kwargs)


client = motor_asyncio.AsyncIOMotorClient()
db = client.db
my_collection = MyCollection(database=db, name='my_collection')
my_collection.my_method()  # my_method () {}
assert db.my_collection == my_collection  # passes assertion