Мы можем объединить две коллекции, используя sub-запрос mongoDB. Вот пример, Комментарии -
`db.commentss.insert([
{ uid:12345, pid:444, comment:"blah" },
{ uid:12345, pid:888, comment:"asdf" },
{ uid:99999, pid:444, comment:"qwer" }])`
Пользователи -
db.userss.insert([
{ uid:12345, name:"john" },
{ uid:99999, name:"mia" }])
Суб-запрос MongoDB для JOIN -
`db.commentss.find().forEach(
function (newComments) {
newComments.userss = db.userss.find( { "uid": newComments.uid } ).toArray();
db.newCommentUsers.insert(newComments);
}
);`
Получить результат из недавно созданная коллекция -
db.newCommentUsers.find().pretty()
Результат -
`{
"_id" : ObjectId("5511236e29709afa03f226ef"),
"uid" : 12345,
"pid" : 444,
"comment" : "blah",
"userss" : [
{
"_id" : ObjectId("5511238129709afa03f226f2"),
"uid" : 12345,
"name" : "john"
}
]
}
{
"_id" : ObjectId("5511236e29709afa03f226f0"),
"uid" : 12345,
"pid" : 888,
"comment" : "asdf",
"userss" : [
{
"_id" : ObjectId("5511238129709afa03f226f2"),
"uid" : 12345,
"name" : "john"
}
]
}
{
"_id" : ObjectId("5511236e29709afa03f226f1"),
"uid" : 99999,
"pid" : 444,
"comment" : "qwer",
"userss" : [
{
"_id" : ObjectId("5511238129709afa03f226f3"),
"uid" : 99999,
"name" : "mia"
}
]
}`
Надеюсь, что это поможет.
Если вы только реализуете методы, то универсальный __getattr__
может сделать трюк
class Wrapper:
def __init__(self, x):
self.x = x
def __getattr__(self, name):
def f(*args, **kwargs):
for y in self.x:
getattr(y, name)(*args, **kwargs)
return f
Например, с x = Wrapper([[], [], []])
после вызова x.append(12)
все три объекта списка будут иметь 12 как последний элемент.
Обратите внимание, что возвращаемое значение всегда будет None
... опция могла бы собирать возвращаемые значения и возвращать их в виде списка, но это, конечно, "сломало бы API".
Я думаю, что у вас есть правильная идея здесь
wrapped_apis = [OriginalApi(), OriginalApi()]
for wrapped_api in wrapped_apis:
wrapped_api.do_something(1, 2, True)
Вы можете определить свой класс-обертку, наследуя из list
, а затем обрабатывать вызовы API для его элементов, как только он будет создан.
class WrapperClass(list):
def __init__(self, api_type):
self.api_type = api_type
for func in dir(api_type):
if callable(getattr(api_type, func)) and not func.startswith("__"):
setattr(self, func, lambda *args, **kwargs:
[getattr(o, func)(*args, **kwargs) for o in self])
w = WrapperClass(OriginalApi)
o1, o2 = [OriginalApi()]*2
w.append(o1)
w.append(o2)
print(w.do_something(1, 2, True))
# [None, None]
print(w[0].b)
# 12
print(w[1].b)
# 12
print(o1.b)
# 12
Здесь я перебираю каждый метод в вашем классе API и создаю метод в классе-обертке, который применяет свои аргументы ко всем своим элементам списка. Затем он возвращает понимание списка, состоящее из результатов.
Излишне говорить, что вам, вероятно, следует проверить тип нового объекта, добавляемого к этому WrapperClass
, например,
def append(self, item):
if not isinstance(item, self.api_type):
raise TypeError('Wrong API type. Expected %s'.format(self.api_type))
super(WrapperClass, self).append(item)