2015-04-29 6 views
1

Я хочу написать простой запрос, который дает мне пользователю наиболее последователям, что имеет часовой пояс бразилия и чирикал 100 или более раз:

это моя линия:

pipeline = [{'$match':{"user.statuses_count":{"$gt":99},"user.time_zone":"Brasilia"}}, 
      {"$group":{"_id": "$user.followers_count","count" :{"$sum":1}}}, 
      {"$sort":{"count":-1}} ] 

Я адаптировал его из практики.

This was given as an example for the structure : 
    { 
    "_id" : ObjectId("5304e2e3cc9e684aa98bef97"), 
    "text" : "First week of school is over :P", 
    "in_reply_to_status_id" : null, 
    "retweet_count" : null, 
    "contributors" : null, 
    "created_at" : "Thu Sep 02 18:11:25 +0000 2010", 
    "geo" : null, 
    "source" : "web", 
    "coordinates" : null, 
    "in_reply_to_screen_name" : null, 
    "truncated" : false, 
    "entities" : { 
     "user_mentions" : [ ], 
     "urls" : [ ], 
     "hashtags" : [ ] 
    }, 
    "retweeted" : false, 
    "place" : null, 
    "user" : { 
     "friends_count" : 145, 
     "profile_sidebar_fill_color" : "E5507E", 
     "location" : "Ireland :)", 
     "verified" : false, 
     "follow_request_sent" : null, 
     "favourites_count" : 1, 
     "profile_sidebar_border_color" : "CC3366", 
     "profile_image_url" : "http://a1.twimg.com/profile_images/1107778717/phpkHoxzmAM_normal.jpg", 
     "geo_enabled" : false, 
     "created_at" : "Sun May 03 19:51:04 +0000 2009", 
     "description" : "", 
     "time_zone" : null, 
     "url" : null, 
     "screen_name" : "Catherinemull", 
     "notifications" : null, 
     "profile_background_color" : "FF6699", 
     "listed_count" : 77, 
     "lang" : "en", 
     "profile_background_image_url" : "http://a3.twimg.com/profile_background_images/138228501/149174881-8cd806890274b828ed56598091c84e71_4c6fd4d8-full.jpg", 
     "statuses_count" : 2475, 
     "following" : null, 
     "profile_text_color" : "362720", 
     "protected" : false, 
     "show_all_inline_media" : false, 
     "profile_background_tile" : true, 
     "name" : "Catherine Mullane", 
     "contributors_enabled" : false, 
     "profile_link_color" : "B40B43", 
     "followers_count" : 169, 
     "id" : 37486277, 
     "profile_use_background_image" : true, 
     "utc_offset" : null 
    }, 
    "favorited" : false, 
    "in_reply_to_user_id" : null, 
    "id" : NumberLong("22819398300") 
} 

Может ли кто-нибудь определить мои ошибки?

+0

Вы пропустили запятую, которая должна разделять контуры трубопровода '$ group' и' $ sort'. – chridam

+0

Исправил его, но все равно получил совершенно неправильный результат :( –

+0

Я обновил ответ с реализацией python, был бы признателен за ваши отзывы. – chridam

ответ

2

Предположим, у вас есть несколько образцов документов с минимальным тестовым случаем. Вставьте тестовые документы в коллекции в mongoshell:

db.collection.insert([ 
{ 
    "_id" : ObjectId("5304e2e3cc9e684aa98bef97"), 
    "user" : { 
     "friends_count" : 145, 
     "statuses_count" : 457, 
     "screen_name" : "Catherinemull", 
     "time_zone" : "Brasilia", 
     "followers_count" : 169, 
     "id" : 37486277 
    }, 
    "id" : NumberLong(22819398300) 
}, 
{ 
    "_id" : ObjectId("52fd2490bac3fa1975477702"), 
    "user" : { 
     "friends_count" : 145, 
     "statuses_count" : 12334, 
     "time_zone" : "Brasilia", 
     "screen_name" : "marble", 
     "followers_count" : 2597, 
     "id" : 37486278 
    }, 
    "id" : NumberLong(22819398301) 
}]) 

Для вас, чтобы получить пользователь с наибольшим количеством последователей, что находится в часовом поясе "Brasilia" и чирикал 100 или более раз, этот трубопровод достигает желаемого результата, но Безразлично» т использовать $group оператор:

pipeline = [ 
    { 
     "$match": { 
      "user.statuses_count": { 
       "$gt":99 
      }, 
      "user.time_zone": "Brasilia" 
     } 
    }, 
    { 
     "$project": {     
      "followers": "$user.followers_count", 
      "screen_name": "$user.screen_name", 
      "tweets": "$user.statuses_count" 
     } 
    }, 
    { 
     "$sort": { 
      "followers": -1 
     } 
    }, 
    {"$limit" : 1} 
] 

PyMongo Выход:

{u'ok': 1.0, 
u'result': [{u'_id': ObjectId('52fd2490bac3fa1975477702'), 
       u'followers': 2597, 
       u'screen_name': u'marble', 
       u'tweets': 12334}]} 

Следующий конвейер агрегации также даст вам желаемый результат. На первом этапе первый этап - это оператор $match, который фильтрует те документы, в которых пользователь имеет значение timezone"Brasilia" и имеет счетчик твитов (представленный statuses_count), который превышает или равен 100, сопоставляемый оператором сравнения $gte.

Второй этап конвейер имеет оператор $group какие группы отфильтрованных документов по указанному выражению идентификатора, который является полем $user.id и применяет выражение аккумулятора $max к каждой группе на поле $user.followers_count, чтобы получить наибольшее количество последователей для каждого пользователя. Системная переменная $$ROOT, которая ссылается на корневой документ, то есть документ верхнего уровня, который в настоящее время обрабатывается на этапе конвейера агрегации $group, добавляется в дополнительное поле массива для последующего использования. Это достигается с помощью оператора массива $addToSet.

Следующий этап трубопровода $unwinds для вывода документа для каждого элемента массива data для обработки на следующем этапе.

Следующий этап перехода, $project, затем преобразует каждый документ в поток путем добавления новых полей, имеющих значения из предыдущего потока.

Последние две стадии трубопровода $sort и $limit переупорядочивает поток документа указанным ключом сортировки followers и возвращает один документ, который содержит пользователя с наибольшим количеством последователей.

Вы окончательный трубопровод агрегации, таким образом, должен выглядеть следующим образом:

db.collection.aggregate([ 
    { 
     '$match': { 
      "user.statuses_count": { "$gte": 100 }, 
      "user.time_zone": "Brasilia" 
     } 
    }, 
    { 
     "$group": { 
      "_id": "$user.id", 
      "max_followers": { "$max": "$user.followers_count" }, 
      "data": { "$addToSet": "$$ROOT" } 
     } 
    }, 
    { 
     "$unwind": "$data" 
    }, 
    { 
     "$project": { 
      "_id": "$data._id", 
      "followers": "$max_followers", 
      "screen_name": "$data.user.screen_name", 
      "tweets": "$data.user.statuses_count" 
     } 
    }, 
    { 
     "$sort": { "followers": -1 } 
    }, 
    { 
     "$limit" : 1 
    } 
]) 

Выполнение этого в Robomongo дает результат

/* 0 */ 
{ 
    "result" : [ 
     { 
      "_id" : ObjectId("52fd2490bac3fa1975477702"), 
      "followers" : 2597, 
      "screen_name" : "marble", 
      "tweets" : 12334 
     } 
    ], 
    "ok" : 1 
} 

В питона, реализация должна быть по существу то же самое:

>>> pipeline = [ 
...  {"$match": {"user.statuses_count": {"$gte":100 }, "user.time_zone": "Brasilia"}}, 
...  {"$group": {"_id": "$user.id","max_followers": { "$max": "$user.followers_count" },"data": { "$addToSet": "$$ROO 
T" }}}, 
...  {"$unwind": "$data"}, 
...  {"$project": {"_id": "$data._id","followers": "$max_followers","screen_name": "$data.user.screen_name","tweets": 
"$data.user.statuses_count"}}, 
...  {"$sort": { "followers": -1 }}, 
...  {"$limit" : 1} 
... ] 
>>> 
>>> for doc in collection.aggregate(pipeline): 
...  print(doc) 
... 
{u'tweets': 12334.0, u'_id': ObjectId('52fd2490bac3fa1975477702'), u'followers': 2597.0, u'screen_name': u'marble'} 
>>> 

, где

pipeline = [ 
    {"$match": {"user.statuses_count": {"$gte":100 }, "user.time_zone": "Brasilia"}}, 
    {"$group": {"_id": "$user.id","max_followers": { "$max": "$user.followers_count" },"data": { "$addToSet": "$$ROOT" }}}, 
    {"$unwind": "$data"}, 
    {"$project": {"_id": "$data._id","followers": "$max_followers","screen_name": "$data.user.screen_name","tweets": "$data.user.statuses_count"}}, 
    {"$sort": { "followers": -1 }}, 
    {"$limit" : 1} 
] 
Смежные вопросы