在App Engine中使用MapReduce创建GROUP BY

时间:2012-02-12 15:38:21

标签: python google-app-engine mapreduce

我正在寻找一种方法,使用MapReduce在数据存储区中的查询中进行GROUP BY操作。 AFAIK App Engine在GQL中不支持GROUP BY本身,其他开发人员建议的好方法是使用MapReduce

我下载了source code,我正在研究demo code,我试图在我的情况下实施。但我没有成功。这是我试图这样做的方式。也许我做的每件事都是错的。所以,如果有人能帮助我做到这一点,我会感谢。


我想要做的是:我在数据存储区中有一堆联系人,每个联系人都有一个日期。在同一个日期有一堆重复的联系人。我想要做的是简单的小组,收集相同日期的相同联系人。

E.g:

假设我有这样的联系方式:

  1. CONTACT_NAME:Foo1 |日期:01-10-2012
  2. CONTACT_NAME:Foo2 |日期:02-05-2012
  3. CONTACT_NAME:Foo1 |日期:01-10-2012
  4. 所以在MapReduce操作之后它会是这样的:

    1. CONTACT_NAME:Foo1 |日期:01-10-2012
    2. CONTACT_NAME:Foo2 |日期:02-05-2012
    3. 对于GROUP BY功能,我认为字数可以完成工作。


      修改

      日志中唯一显示的是:

        

      / mapreduce / pipeline / run 200

           

      运行GetContactData.WordCountPipeline((u'2012-02-02',),   * {})#da26a9b555e311e19b1e6d324d450c1a

      结束编辑

      如果我做错了,如果我使用错误的方法用MapReduce做GROUP BY,请帮我解决如何使用MapReduce。


      这是我的代码:

      from Contacts import Contacts
      from google.appengine.ext import webapp
      from google.appengine.ext.webapp import template
      from google.appengine.ext.webapp.util import run_wsgi_app
      from google.appengine.api import mail
      from google.appengine.ext.db import GqlQuery
      from google.appengine.ext import db
      
      
      from google.appengine.api import taskqueue
      from google.appengine.api import users
      
      from mapreduce.lib import files
      from mapreduce import base_handler
      from mapreduce import mapreduce_pipeline
      from mapreduce import operation as op
      from mapreduce import shuffler
      
      import simplejson, logging, re
      
      
      class GetContactData(webapp.RequestHandler):
      
          # Get the calls based on the user id
          def get(self):
              contactId = self.request.get('contactId')
              query_contacts = Contact.all()
              query_contacts.filter('contact_id =', int(contactId))
              query_contacts.order('-timestamp_')
              contact_data = []
              if query_contacts != None:
                  for contact in query_contacts:
                          pipeline = WordCountPipeline(contact.date)
                          pipeline.start()
                          record = { "contact_id":contact.contact_id,
                                     "contact_name":contact.contact_name,
                                     "contact_number":contact.contact_number,
                                     "timestamp":contact.timestamp_,
                                     "current_time":contact.current_time_,
                                     "type":contact.type_,
                                     "current_date":contact.date }
                          contact_data.append(record)
      
              self.response.headers['Content-Type'] = 'application/json'
              self.response.out.write(simplejson.dumps(contact_data)) 
      
      class WordCountPipeline(base_handler.PipelineBase):
        """A pipeline to run Word count demo.
      
        Args:
          blobkey: blobkey to process as string. Should be a zip archive with
            text files inside.
        """
      
        def run(self, date):
          output = yield mapreduce_pipeline.MapreducePipeline(
              "word_count",
              "main.word_count_map",
              "main.word_count_reduce",
              "mapreduce.input_readers.DatastoreInputReader",
              "mapreduce.output_writers.BlobstoreOutputWriter",
              mapper_params={
                  "date": date,
              },
              reducer_params={
                  "mime_type": "text/plain",
              },
              shards=16)
          yield StoreOutput("WordCount", output)
      
      class StoreOutput(base_handler.PipelineBase):
        """A pipeline to store the result of the MapReduce job in the database.
      
        Args:
          mr_type: the type of mapreduce job run (e.g., WordCount, Index)
          encoded_key: the DB key corresponding to the metadata of this job
          output: the blobstore location where the output of the job is stored
        """
      
        def run(self, mr_type, output):
            logging.info(output) # here I should append the grouped duration in JSON
      

1 个答案:

答案 0 :(得分:0)

我基于此question中提供的代码@autumngard并进行了修改,以符合我的目的并且有效。