我正在尝试创建一个系统来追踪我应用程序上的拆分测试。每个用户被分配一个整数,代表他们的状态,然后我存储每次访问,其中访问具有引用用户文档。下面的查询应该给我那些 test_subject 字段为 0 的用户的每天平均在线时间。
我的当前架构如下:
class Visits(Document):
year = IntField(default=datetime.datetime.now().year)
month = IntField(default=datetime.datetime.now().month)
day = IntField(default=datetime.datetime.now().day, unique_with=('month', 'year'))
visits = ListField(EmbeddedDocumentField('Visit'))
class Posts(Document):
year = IntField(default=datetime.datetime.now().year)
month = IntField(default=datetime.datetime.now().month)
day = IntField(default=datetime.datetime.now().day, unique_with=('month', 'year'))
posts = ListField(EmbeddedDocumentField('Post'))
class Visit(Document):
user = ReferenceField('User')
time_spent = IntField(default=0)
class Post(Document):
id = IntField(primary_key=True)
user = ReferenceField('User')
number_of_comments = IntField(default=0)
number_of_clicks = IntField(default=0)
class User(Document):
id = IntField(primary_key=True)
created_at = DateTimeField(default=datetime.datetime.now())
test_subject = IntField(default="0")
我目前的查询如下:
def aa(request):
year = datetime.datetime.now().year
month = datetime.datetime.now().month
result = Visits._get_collection().aggregate([
{
"$unwind": "$visits"
},
{
"$match": {"visits.user.test_subject" : 0}
},
{"$group": {
"_id": {
"day": "$day"
},
"visits": {
"$avg": "$visits.time_spent"
}
}}
])
return result
出于某种原因,输出总是空数组。
解决方案
MongoDB没有连接,你不能聚合来自3个单独集合的数据。你的问题是你在尝试在嵌入文档时创建单独的集合。你的 Post、Visit 和 User 类应该继承自 EmbeddedDocument,而不是 Document。这样,你的 Visits 集合将具有嵌入式文档,然后你可以在该集合上运行你的聚合。
以下是修改后的代码:
from mongoengine import *
class Visits(Document):
year = IntField(default=datetime.datetime.now().year)
month = IntField(default=datetime.datetime.now().month)
day = IntField(default=datetime.datetime.now().day, unique_with=('month', 'year'))
visits = ListField(EmbeddedDocumentField('Visit'))
class Posts(Document):
year = IntField(default=datetime.datetime.now().year)
month = IntField(default=datetime.datetime.now().month)
day = IntField(default=datetime.datetime.now().day, unique_with=('month', 'year'))
posts = ListField(EmbeddedDocumentField('Post'))
class Visit(EmbeddedDocument):
user = ReferenceField('User')
time_spent = IntField(default=0)
class Post(EmbeddedDocument):
id = IntField(primary_key=True)
user = ReferenceField('User')
number_of_comments = IntField(default=0)
number_of_clicks = IntField(default=0)
class User(Document):
id = IntField(primary_key=True)
created_at = DateTimeField(default=datetime.datetime.now())
test_subject = IntField(default="0")
def aa(request):
year = datetime.datetime.now().year
month = datetime.datetime.now().month
result = Visits._get_collection().aggregate([
{
"$unwind": "$visits"
},
{
"$match": {"visits.user.test_subject" : 0}
},
{"$group": {
"_id": {
"day": "$day"
},
"visits": {
"$avg": "$visits.time_spent"
}
}}
])
return result
现在,运行 aa() 函数应该会给你那些 test_subject 字段为 0 的用户的每天平均在线时间。