2012-09-29 3 views
2

Twitter API에서 스트림 데이터를 가지고 있으며 데이터가 MongoDB에 문서로 저장되어 있다고 가정 해 보겠습니다. 내가 찾고자하는 것은 screen_name의 수를 entities.user_mentions 아래에 둔다.Twitter 데이터 - MongoDB에서 가장 많이 언급 된 사용자 찾기

{ 
    "_id" : ObjectId("50657d5844956d06fb5b36c7"), 
    "contributors" : null, 
    "text" : "", 
    "entities" : { 
     "urls" : [ ], 
     "hashtags" : [ 
      { 
       "text" : "", 
       "indices" : [ 
        26, 
        30 
       ] 
      }, 
      { 
       "text" : "", 
       "indices" : [] 
      } 
     ], 
     "user_mentions" : [ 
       { 
        "name":"Twitter API", 
        "indices":[4,15], 
        "screen_name":"twitterapi", 
        "id":6253282, "id_str":"6253282" 
       }] 
    }, 
    ... 

내가지도를 사용하는 시도가 감소 :

map = function() { 
    if (!this.entities.user_mentions.screen_name) { 
     return; 
    } 

    for (index in this.entities.user_mentions.screen_name) { 
     emit(this.entities.user_mentions.screen_name[index], 1); 
    } 
} 

reduce = function(previous, current) { 
    var count = 0; 

    for (index in current) { 
     count += current[index]; 
    } 

    return count; 
} 

result = db.runCommand({ 
    "mapreduce" : "twitter_sample", 
    "map" : map, 
    "reduce" : reduce, 
    "out" : "user_mentions" 
}); 

그러나 그 아주 작동하지 ...

답변

3

entities.user_mentions 때문에 것은 배열, 각 SCREEN_NAME에 대한 값을 방출 할 것입니다 the map() :

var map = function() { 
    this.entities.user_mentions.forEach(function(mention) { 
     emit(mention.screen_name, { count: 1 }); 
    }) 
}; 

그런 다음 고유 한 screen_n reduce()에서 화염 :

var reduce = function(key, values) { 
    // NB: reduce() uses same format as results emitted by map() 
    var result = { count: 0 }; 

    values.forEach(function(value) { 
     result.count += value.count; 
    }); 

    return result; 
}; 

참고 :이 print()printjson() 명령을 사용할 수 있습니다, /지도를 자바 스크립트 디버깅 기능을 줄일 수 있습니다. 출력은 mongod 로그에 나타납니다.

편집 트위터 데이터로 암시 된 바와 같이

db.twitter_sample.aggregate(
    // Project to limit the document fields included 
    { $project: { 
     _id: 0, 
     "entities.user_mentions" : 1 
    }}, 

    // Split user_mentions array into a stream of documents 
    { $unwind: "$entities.user_mentions" }, 

    // Group and count the unique mentions by screen_name 
    { $group : { 
     _id: "$entities.user_mentions.screen_name", 
     count: { $sum : 1 } 
    }}, 

    // Optional: sort by count, descending 
    { $sort : { 
     "count" : -1 
    }} 
) 

원래지도/접근을 줄이고 큰 데이터 세트에 적합하다 : 비교를 위해, 여기 MongoDB를 2.2 새로운 Aggregation Framework를 사용한 예이다. Map/Reduce와 Aggregation Framework 제한을 비교하기 위해 StackOverflow 질문 MongoDB group(), $group and MapReduce에 대한 관련 토론을 참조하십시오.

+0

모자를 벗으십시오. Aggregate Framework를 사용하여 동일한 작업을 수행 할 수 있습니까? 'group()'함수는 무엇입니까? – chutsu

+1

@chutsu : Aggregation Framework에서도 동일한 작업을 수행 할 수 있지만 결과는 인라인으로 제한되고 최대 문서 크기는 16Mb로 제한된다는 몇 가지주의 사항이 있습니다. 'group()'명령을 사용하는 것도 가능할 수 있지만, 이것 역시 몇 가지 제한이 있습니다. 접근법과 한계를 비교하기 위해 [MongoDB group(), $ group and MapReduce] (http://stackoverflow.com/questions/12337319/mongodb-group-group-and-mapreduce/12340283#12340283)를 참조하십시오. – Stennie

+1

@chutsu : 집계 프레임 워크 예제를 추가했습니다. – Stennie

관련 문제