【问题标题】:PyMongo(3.6.1) - db.collection.aggregate(pipeline) NOT WORKINGPyMongo(3.6.1) - db.collection.aggregate(pipeline) 不工作
【发布时间】: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


【解决方案1】:

我认为您需要在迭代之前将光标投射到列表中。希望这会有所帮助。

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

【讨论】:

  • 感谢您的帮助,但我已经尝试过了,仍然无法正常工作。我认为问题在于 pymongo 如何详细说明查询,因为光标是空的,即使我将其转换为列表,它也找不到任何与聚合方法匹配的内容。
  • 为什么要为聚合函数使用第二个参数,它有什么作用?
猜你喜欢
  • 1970-01-01
  • 2016-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-28
相关资源
最近更新 更多