PyMongo(3.6.1) - db.collection.aggregate(管道)不工作

时间:2018-05-31 07:23:43

标签: mongodb aggregation-framework pymongo pipeline

我在使用PyMongo时遇到了麻烦,我一直在谷歌搜索数小时,但没有找到解决办法。

我正在使用一些Python脚本来练习在本地计算机上运行的MongoDb。我用一个数据库" moviesDB"填充了我的mongoDb实例,其中包含3个不同的集合:

1. 电影收藏,以下是此文章中的文件示例:

{'_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.Taggo collection,我在这里没有使用过,所以它并不重要。

现在,我尝试做的是:给予用户(在此示例中为用户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)

关键是电影集合上的聚合函数检索NOTHING,而它确实应该,因为我在MongoShell上尝试了这个查询,它运行得很好。以下是mongoDB shell查询的外观:

db.movies.aggregate(
[
    {$match:{_id : {$in: ids}}},
    {$unwind : "$genres"},
    {$group :
        {
            _id : "$genres",
            movies: { $addToSet : "$_id" }}}
]

);

' id'变量是这样定义的,就像代码中的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 ] }

现在问题是聚合方法,管道字符串是否有错误?

请帮助!! 谢谢

1 个答案:

答案 0 :(得分:0)

我认为你需要在迭代之前将光标转换为列表。希望这会有所帮助。

cursor = list(db.movies.aggregate(pipeline, cursor={}))