【发布时间】:2018-05-31 17:41:35
【问题描述】:
我在使用 PyMongo 时遇到问题,我已经搜索了几个小时,但没有找到解决方案。
我正在使用一些 Python 脚本,只是为了练习在我的本地机器上运行的 MongoDb。我用一个数据库“moviesDB”填充了我的 mongoDb 实例,其中包含 3 个不同的集合:
1.电影合集,这里有一个来自这个coll的文档示例:
{'_id': 1,
'title': 'Toy Story (1995)',
'genres': ['Adventure', 'Animation', 'Children', 'Comedy', 'Fantasy'],
'averageRating': 3.87,
'numberOfRatings': 247,
'tags': [
{'_id': ObjectId('5b04970b87977f1fec0fb6e9'),
'userId': 501,
'tag': 'Pixar',
'timestamp': 1292956344}
]
}
2.评分集合,如下所示:
{ '_id':ObjectId('5b04970c87977f1fec0fb923'),
'userId': 1,
'movieId': 31,
'rating': 2.5,
'timestamp': 1260759144}
3.Tags 集合,我不会在这里使用,所以它并不重要。
现在,我要做的是:给定一个用户(在本例中为用户 1),找到他评价的所有电影类型,并按每个类型列出与该类型有关的所有电影 ID。 这是我的代码:
"""
This query basically retrieves movieIds,
so from the result list of several documents like this:
{
ObjectId('5b04970c87977f1fec0fb923'),
'userId': 1,
'movieId': 31,
'rating': 2.5,
'timestamp': 1260759144},
retrieves only an array of integers, where each number represent a movie
that the user 1 rated."""
movies_rated_by_user = list(db.ratings.distinct(movieId, {userId: 1}))
pipeline = [
{"$match": {"_id ": {"$in": movies_rated_by_user}}},
{"$unwind": "$genres"},
{"$group": {"_id": "$genres", "movies": {"$addToSet": "$_id"}}}]
try:
"""HERE IS THE PROBLEM, SINCE db.movies.aggregate() RETURNS NOTHING!
so the cursor is empty."""
cursor = db.movies.aggregate(pipeline, cursor={})
except OperationFailure:
print("Something went Wrong", file=open("operations_log.txt", "a"))
print(OperationFailure.details, file=open("operations_log.txt", "a"))
sys.exit(1)
aggregate_genre = []
for c in cursor:
aggregate_genre.append(c)
print(aggregate_genre)
关键是电影集合上的聚合函数什么都不检索,而它确实应该检索,因为我在 MongoShell 上尝试了这个查询,它工作得很好。下面是 mongoDB shell-query 的样子:
db.movies.aggregate(
[
{$match:{_id : {$in: ids}}},
{$unwind : "$genres"},
{$group :
{
_id : "$genres",
movies: { $addToSet : "$_id" }}}
]
);
'ids' 变量的定义是这样的,就像代码中的 movies_rated_by_user 变量一样:
ids= db.ratings.distinct("movieId", {userId : 1});
聚合方法的结果如下所示(这是代码中的 aggregate_genre 变量,应该包含的内容):
{ "_id" : "Western", "movies" : [ 3671 ] }
{ "_id" : "Crime", "movies" : [ 1953, 1405 ] }
{ "_id" : "Fantasy", "movies" : [ 2968, 2294, 2193, 1339 ] }
{ "_id" : "Comedy", "movies" : [ 3671, 2294, 2968, 2150, 1405 ] }
{ "_id" : "Sci-Fi", "movies" : [ 2455, 2968, 1129, 1371, 2105 ] }
{ "_id" : "Adventure", "movies" : [ 2193, 2150, 1405, 1287, 2105, 2294,
2968, 1371, 1129 ] }
现在问题是聚合方法,管道字符串有什么错误吗??
请帮忙!! 谢谢
【问题讨论】:
-
慢下来。你一直在编辑,你已经要求太多了。只需开始调试问题。您正在向
$match发送值列表,它们是什么?他们应该匹配哪些文件?只需向我们展示值列表以及您希望它们匹配的内容即可。当您没有得到任何结果时,这是您“哪里出了问题”的第一站。 -
抱歉编辑太多,我正在尝试解决一些问题。
-
无论如何,movies_rated_by_user 包含了所有的评分记录,其中用户号 1 出现为 userId,即进行评分的用户。我使用了“不同的方法”,以便它只返回用户评价的电影的 moviesId,并从电影集合中只匹配用户评价的那些电影。本质上是一个整数数组,代表movieIds。
-
您真正需要关注的唯一编辑是提供Minimal, Complete, and Verifiable example。这意味着显示您对任何变量的输入,并显示您期望从中合理返回所需结果的示例文档。如果你给人们一些他们实际上可以复制的东西,它会让发现问题和建议做什么比浏览一个问题的代表作要简单得多。一个好的问题不必是一个生活故事,只需要提供正确的细节来解决它。
-
现在好点了吗?我只减少了问题所在的代码。
标签: mongodb aggregation-framework pymongo pipeline