因此,我在应用程序中使用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'}})
答案 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