SlideShare a Scribd company logo
1 of 44
Download to read offline
Migrating from MySQL to MongoDB at Sluggy.com

                                  Brendan W. McAdams

                                    Evil Monkey Labs, LLC


                     Mongo Boston Conference - Sep. 20, 2010




B.W. McAdams (Evil Monkey Labs)    Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   1 / 42
Outline

1   Introduction
       Basic Rundown
       Technology History

2   What We Learned
     Lessons Learned Over Time
     Open Source Code Yielded
     Why MongoDB?

3   Show Me The Code!
      The Old: MySQL Snippets

4   Final Items



B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   2 / 42
Outline

1   Introduction
       Basic Rundown
       Technology History

2   What We Learned
     Lessons Learned Over Time
     Open Source Code Yielded
     Why MongoDB?

3   Show Me The Code!
      The Old: MySQL Snippets

4   Final Items



B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   3 / 42
Sluggy.com Rundown

      Live since August 25, 1997
      Updated Every Day (even if it’s just filler)
      More Users == More Load
      More Load == More Hardware
      On Advertising Revenues (e.g. Paying the Bills), Pete says:                        I tend

      to think of advertising as a finky spastic mentally retarded cat who sometimes wants to

      jump in my lap and other times wants to hiss at me and run for the litterbox and often

      walks in circles trying to figure out which of the two it wants, followed by dropping

      dead with a final thought..."ohhh!   food!"

      Not Google... Not Trying to be Google. (Can’t afford to think or
      scale like Google.
      No dedicated staff or operations budget - advertising revenues
      cover server costs. Any downtime (be it bugs or system failure)
      means I get up at 3am to fix it.

B.W. McAdams (Evil Monkey Labs)    Sluggy.com: MySQL to MongoDB       Mongo Boston - 9/20/10   4 / 42
Sluggy.com Rundown

      Live since August 25, 1997
      Updated Every Day (even if it’s just filler)
      More Users == More Load
      More Load == More Hardware
      On Advertising Revenues (e.g. Paying the Bills), Pete says:                        I tend

      to think of advertising as a finky spastic mentally retarded cat who sometimes wants to

      jump in my lap and other times wants to hiss at me and run for the litterbox and often

      walks in circles trying to figure out which of the two it wants, followed by dropping

      dead with a final thought..."ohhh!   food!"

      Not Google... Not Trying to be Google. (Can’t afford to think or
      scale like Google.
      No dedicated staff or operations budget - advertising revenues
      cover server costs. Any downtime (be it bugs or system failure)
      means I get up at 3am to fix it.

B.W. McAdams (Evil Monkey Labs)    Sluggy.com: MySQL to MongoDB       Mongo Boston - 9/20/10   4 / 42
Sluggy.com Rundown

      Live since August 25, 1997
      Updated Every Day (even if it’s just filler)
      More Users == More Load
      More Load == More Hardware
      On Advertising Revenues (e.g. Paying the Bills), Pete says:                        I tend

      to think of advertising as a finky spastic mentally retarded cat who sometimes wants to

      jump in my lap and other times wants to hiss at me and run for the litterbox and often

      walks in circles trying to figure out which of the two it wants, followed by dropping

      dead with a final thought..."ohhh!   food!"

      Not Google... Not Trying to be Google. (Can’t afford to think or
      scale like Google.
      No dedicated staff or operations budget - advertising revenues
      cover server costs. Any downtime (be it bugs or system failure)
      means I get up at 3am to fix it.

B.W. McAdams (Evil Monkey Labs)    Sluggy.com: MySQL to MongoDB       Mongo Boston - 9/20/10   4 / 42
Sluggy.com Rundown
Some Stats




        50GB/day (1.5TB of traffic/month on a single virtual box)
       13 years of daily comics = 6500 image files (just for the comics)
       Artist is frequently late in updating. System has to handle random
       unexpected cache flushes & data updates.
       Erratic access behavior: Today’s comic is always popular and
       related load can be easily mitigated. However, archives may also
       be hit heavily by new readers or links from a newer strip to
       previous storylines. Hard to expect where in 6500+ strips people
       may be digging from day to day.
       “LUMP” Stack (Lighttpd, Ubuntu, MongoDB & Python)



 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   5 / 42
Outline

1   Introduction
       Basic Rundown
       Technology History

2   What We Learned
     Lessons Learned Over Time
     Open Source Code Yielded
     Why MongoDB?

3   Show Me The Code!
      The Old: MySQL Snippets

4   Final Items



B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   6 / 42
Sluggy.com Technology History
1997 - 2000


       August 25, 1997: Site Started, with basic code by Pete‘s
       friends/coworkers.
       Static HTML generated via midnight cron executing Perl.
       No dynamic content - Hand edited HTML for news, navigation, etc.
       File format requires globs:
       000217a.gif
       000217b.gif
       000217c.gif
       All make up the panels for February 17, 2000. Artist likes &
       understands this format. Code looks for yyMMdd*.(gif|jpg)
       via glob and organizes them in order.
       2000 - Original Developers split off and formed KeenSpot.com
       using same code & navigation concepts.

 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   7 / 42
Sluggy.com Technology History
2002



       Rewrite using MySQL & PHP (original goal: “No More HTML
       Editing”)
       Scope Creep == New Features. Dynamic headlines, news,
       predefined templates, dynamic navigation and a “Members Only
       Club”.
       First Folly - Reading MySQL and dynamically generating on each
       page request; Running dynamic code for essentially static content
       == FAIL. Disk I/O DoSing ... “call datacenter and cross fingers”
       Moved to smarty template caching, generating on-disk cache file
       upon first request (expires at midnight).
       Next 4 years became hellish with frequent Midnight
       crashes/failures as readers pound server for new comic.


B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   8 / 42
Sluggy.com Technology History I
2006



       Server move (For cost reasons) introduced new architecture
       problems
       Perceived cost savings pushed a move from SCSI/SAS disks to
       SATA
             Between template files & comic file globs. Disks couldn’t keep up.
             Implemented memcached to cache templates off-disk, in memory.
             Cached glob results (but not files). Cached anything else not likely
             to change - expiry set to a week (midnight for “index”)
             Sessions performed poorly in both disk and MySQL - caching in
             memcached helped.
       Apache began crushing memory & disk I/O.
             PHP isn’t thread safe; requires forked Apache workers (children are
             EXPENSIVE)


B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   9 / 42
Sluggy.com Technology History II
2006


             Migrated to Lighttpd + FastCGI - IO & RAM usage of webserver &
             PHP became negligible (Lots of tweaking of handling of static files
             esp. stat caching w/ FAM & good event handling):
              # without raising default fds (1024) we hit a lot of out of fds @ midnight
              # File descriptors include network connections *AND* filesystem handles...
              server.max-fds = 4096
              # Use a well tuned event handler for connection handling
              server.event-handler = "linux-sysepoll"
              # Don’t shred the disk pulling static files; w/o a custom engine
              # like fam stat() runs for *EVERY* static file fetch.
              server.stat-cache-engine = "fam"
              # Severely limiting keep-alives paired w/ good Expires headers
              server.max-keep-alive-requests = 4
              server.max-keep-alive-idle = 2
              # Ask politely that browsers don’t keep redownloading static content
              expire.url = (
                "/javascripts/" => "access 2 weeks",
                "/stylesheets/" => "access 2 weeks",
                "/icons/" => "access 2 weeks",
                "/images" => "access 1 weeks",
                "/images/comics/" => "access 1 days"
              )




B.W. McAdams (Evil Monkey Labs)     Sluggy.com: MySQL to MongoDB      Mongo Boston - 9/20/10   10 / 42
Sluggy.com Technology History
2009




       Rewrote the system in Pylons (Python + SQLAlchemy[MySQL])
       Integrated Beaker caching decorators (templates & code blocks) -
       simplified adding caching code at need.
       Clean ORM model, light & fast with lots of caching.
       Ran significantly better than on PHP - infinitely more tunable,
       sensible, and sane (Not necessarily a knock on PHP - but it was a
       10 year old codebase).
       memcached continued to become a big, rickety crutch (cascading
       failure sucks)




B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   11 / 42
Sluggy.com Technology History
Aug. 2009




       August 3, 2009: Pylons system (v1.0) Live with MySQL backend.
       Huge amounts of our code (as much as 80%) was dedicated to
       converting UI Objects to and from Database objects. WTF?...
       Most initial bugs occurred in this model <-> view layer.
       No more forking - Pylons & Python run threaded via SCGI (Similar
       to FastCGI). System resources significantly less taxed by the
       presentation stack.




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   12 / 42
Sluggy.com Technology History
Aug. 2009


       August 14, 2009: v1.10 Went Live - MySQL replaced by
       MongoDB (and MongoKit)
       Easy Migration - MongoKit was quickly dropped in place and
       queries adjusted to new model (Stuck to MySQL schema as much
       as possible)
       Maintained all bug fixes on MySQL branch for a few weeks “just in
       case”
       Performance vastly improved.
       Over next few months, built tools to use MongoDB in place of
       memcached for caching (mongodb_beaker)
       LAMP replaced by LUMP (Lighttpd, Ubuntu, MongoDB & Python)
       A few things left in memcached through a combination of “makes
       sense there” and indolence.

 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   13 / 42
Sluggy.com Technology History
Sept. 2009




       MongoDB completely obviated dependency on dedicated Physical
       hardware; when a major issue with our ISP came up, migrated to
       Virtual hosting (slicehost) instead of Physical Hardware.
       Average system load is 0.05 on a 2G slice.
       MongoDB uses 1% of CPU on average.
       Switchover to MongoDB version took 2 minutes (ran data
       conversion script, deployed new code tag, bounced webserver /
       Pylons app)
       No downtime in any way attributable to MongoDB since go live -
       now live with MongoDB over a year.



 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   14 / 42
Outline

1   Introduction
       Basic Rundown
       Technology History

2   What We Learned
     Lessons Learned Over Time
     Open Source Code Yielded
     Why MongoDB?

3   Show Me The Code!
      The Old: MySQL Snippets

4   Final Items



B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   15 / 42
memcached can rapidly become a crutch. . .
meant to make up for RDBMS’ shortfalls but often masks other issues. . .




       memcached can be great for things you can afford to lose.
       It’s not just about what you “can’t afford to lose”. Beware of
       cascading failures.
       Over reliance can cause self-DoSing after a crash, reboot,
       accidental flush (even of just one keyset) etc... Lesson learned the
       hard way.
       See Coders at Work (Siebel) for a great discussion with its
       creator, Brian Fitzpatrick (founded LiveJournal & now a Google
       employee), about what led to memcached’s creation.




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   16 / 42
As long as I’m being hyperbolic. . . I
MongoDB is a bionic leg replacement. . .

       MongoDB’s MMAP system gives you a “free” MRU cache. Done
       right and simple; caching on MongoDB is durable, light and fast.
       Significantly educes amount of scalability-glue code.
       No piles of special code manage caching; if it falls out of memory
       cache, it is still safely persisted to disk.
       The more you can put in memory, the less you beat on your disks.
       Especially important on virtual hosting: Be a Good Neighbor.
       But. . . don’t build your MongoDB system like a MySQL system (it’ll
       work, but you rapidly lose speed and flexibility)




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   17 / 42
As long as I’m being hyperbolic. . . II
MongoDB is a bionic leg replacement. . .




              DBRefs should be used sparingly - favor embedded objects (don’t
              be afraid to denormalize and duplicate data); autorefs can be even
              worse as there’s a performance penalty imposed.
              Flexible schemas are good.
              Wasting your time mapping data back and forth between your
              presentation layer & RDBMS is not just tedious - it’s error prone.
              Object Mappers for MongoDB are fantastic tools but don’t overuse
              them - you take a huge flexibility & performance hit.
              Use field specifications, query operators, and atomic updates for
              maximum effectiveness. MongoDB excels at slicing out specific
              parts of a document - especially from embedded/nested fields.




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   18 / 42
Caveats


      While there is a lot “wrong” with our first pass implementation,
      MongoDB has been consistent, performant and most importantly:
      forgiving.
      Someone has to enforce a consistent schema - if it’s not your
      datastore (like a RDBMS does) then your code or ops people (or
      both) have to.
      The MongoDB community is vibrant, supportive and consistently
      brilliant. Use your community to build the best possible product.
      Corollary: If there is not a vibrant, supportive and intelligent
      community behind a product you are evaluating. . . run.
      Participate: A community that takes and never gives back cannot
      thrive. Sharing your knowledge and experience goes a long way.



B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   19 / 42
Outline

1   Introduction
       Basic Rundown
       Technology History

2   What We Learned
     Lessons Learned Over Time
     Open Source Code Yielded
     Why MongoDB?

3   Show Me The Code!
      The Old: MySQL Snippets

4   Final Items



B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   20 / 42
Open Source Code I
mongodb_beaker: Beaker Caching for MongoDB



       Open Source caching plugin for the Python Beaker stack.
       Uses distutils plugin entry points.
       Switching from memcached to Beaker + MongoDB required a 2
       line config file change:
        -   beaker.session.type = libmemcached
        -   beaker.session.url = 127.0.0.1:11211
        +   beaker.session.type = mongodb
        +   beaker.session.url = mongodb://localhost:27017/emergencyPants#sessions


       Lots of useful options in MongoDB Beaker.
       A few limitations on the beaker side which need changes in
       Beaker (manipulable cache data).
       Patch incubating for better replica, shard and master/slave
       support.


 B.W. McAdams (Evil Monkey Labs)      Sluggy.com: MySQL to MongoDB      Mongo Boston - 9/20/10   21 / 42
Open Source Code I
MongoKit-Pylons: Pylons patches for Python MongORM

       Added support to MongoKit to run within a Pylons environment
       (threadlocal setup of connection pool)
       Adding a globally available thread safe connection pool to Pylon
       was simple. Add 2 lines to config/environment.py:
        from mongokit.ext.pylons_env import MongoPylonsEnv
        MongoPylonsEnv.init_mongo()




 B.W. McAdams (Evil Monkey Labs)    Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   22 / 42
Open Source Code II
MongoKit-Pylons: Pylons patches for Python MongORM




       Added a few other features to simplify SQLAlchemy migration
              setattr / getattr support to allow mongoDoc.field instead of the dict
              interface (mongoDoc[’field’])
              DB Authentication
              A few missing corners such as additional datatypes, enhanced
              index definitions on-document, group statement shortcuts, etc.
              Integrated support for autoreferences (which was/are mostly a very
              bad idea)
       Changes merged into MongoKit Trunk (MongoKit has stellar unit
       test coverage)




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   23 / 42
Outline

1   Introduction
       Basic Rundown
       Technology History

2   What We Learned
     Lessons Learned Over Time
     Open Source Code Yielded
     Why MongoDB?

3   Show Me The Code!
      The Old: MySQL Snippets

4   Final Items



B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   24 / 42
Why MongoDB?

      Dynamic Querying
      Flexibility (embedded documents, atomic updates, query
      operators and server-side javascript.)
      CouchDB’s approach appeared obtuse and rather unPythonic (not
      an indictment of CouchDB, simply reflective of my knowledge &
      opinion at the time)
      Tools like MongoKit allowed for easy replacement of existing
      MySQL ORM code with something almost identical
      FAST
      Great Support & Community Available.
             Core developers/founders have serious experience in real
             scalability, and are active in community.
             MongoDB Mailing List
             IRC: freenode.net #mongodb

B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   25 / 42
Outline

1   Introduction
       Basic Rundown
       Technology History

2   What We Learned
     Lessons Learned Over Time
     Open Source Code Yielded
     Why MongoDB?

3   Show Me The Code!
      The Old: MySQL Snippets

4   Final Items



B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   26 / 42
MySQL Schema Snippets I
The Admin Table...




 CREATE TABLE ‘admin_users‘ (
   ‘id‘ int(11) unsigned NOT NULL auto_increment,
   ‘username‘ varchar(45) collate latin1_general_ci NOT NULL default ’’,
   ‘password‘ char(32) collate latin1_general_ci NOT NULL,
   ‘display_name‘ varchar(64) collate latin1_general_ci default NULL,
   ‘email‘ varchar(255) collate latin1_general_ci NOT NULL default ’’,
   ‘avatar‘ varchar(255) collate latin1_general_ci default NULL,
   ‘last_ip‘ int(10) unsigned default NULL,
   ‘last_login_date‘ timestamp NOT NULL default ’0000-00-00 00:00:00’,
   ‘disabled‘ tinyint(1) default ’0’,
   PRIMARY KEY (‘id‘),
   UNIQUE KEY ‘UNIQUE‘ (‘username‘),
   UNIQUE KEY ‘admin_users_uniq‘ (‘email‘)
 ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci
       PACK_KEYS=1;




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB      Mongo Boston - 9/20/10   27 / 42
MySQL Schema Snippets I
The News Table...




 CREATE TABLE ‘news‘ (
   ‘id‘ int(11) unsigned NOT NULL auto_increment,
   ‘author_id‘ int(11) unsigned NOT NULL,
   ‘start_date‘ date NOT NULL,
   ‘end_date‘ date default NULL,
   ‘headline‘ varchar(255) NOT NULL,
   ‘story‘ text NOT NULL,
   ‘archive‘ tinyint(1) default ’0’,
   PRIMARY KEY (‘id‘),
   KEY ‘news_author‘ (‘author_id‘),
   CONSTRAINT ‘news_author‘ FOREIGN KEY (‘author_id‘) REFERENCES ‘admin_users‘ (‘id‘)
 ) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=latin1;




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB      Mongo Boston - 9/20/10   28 / 42
SQLAlchemy Model I
The Admin Object




 class AdminUser(ORMObject):
     pass

 t_admin_users = Table(’admin_users’, meta.metadata,
     Column(’id’, Integer, primary_key=True),
     Column(’username’, Unicode(45), nullable=False, unique=True),
     Column(’password’, Unicode(32), nullable=False),
     Column(’display_name’, Unicode(64)), # Should be unique?
     Column(’email’, Unicode(255), nullable=False, unique=True),
     Column(’last_ip’, IPV4Address, nullable=True),
     Column(’last_login_date’, MSTimeStamp, nullable=False),
     Column(’avatar’, Unicode(255), nullable=True),
     Column(’disabled’, Boolean, default=False),
     mysql_engine=’InnoDB’
 )

 mapper(AdminUser, t_admin_users)




 B.W. McAdams (Evil Monkey Labs)    Sluggy.com: MySQL to MongoDB     Mongo Boston - 9/20/10   29 / 42
SQLAlchemy Model I
The News Object




 class NewsStory(ORMObject):
     pass

 t_news = Table(’news’, meta.metadata,
     Column(’id’, Integer, primary_key=True),
     Column(’author_id’, Integer, ForeignKey(’admin_users.id’), nullable=False),
     Column(’start_date’, Date, nullable=False),
     Column(’end_date’, Date),
     Column(’headline’, Unicode(255), nullable=False),
     Column(’story’, Unicode, nullable=False),
     Column(’archive’, Boolean, default=False),
     mysql_engine=’InnoDB’
 )

 mapper(NewsStory, t_news, properties={
     ’author’: relation(AdminUser, backref=’news_stories’)
 })




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB      Mongo Boston - 9/20/10   30 / 42
SQLAlchemy Model I
Paypal: OH THE HORROR

 class PaypalIPN(ORMObject):
     pass


 t_paypal_ipn = Table(’paypal_ipn’, meta.metadata,
     Column(’id’, Integer, primary_key=True),
     Column(’first_name’, Unicode(64)),
     Column(’last_name’, Unicode(64)),
     Column(’payer_business_name’, Unicode(127)),
     Column(’payer_email’, Unicode(127)),
     Column(’payer_id’, Unicode(13)),
     Column(’payer_status’, Unicode(10)),
     Column(’residence_country’, Unicode(2)),
     Column(’business’, Unicode(127)),
     Column(’receiver_email’, Unicode(127)),
     Column(’receiver_id’, Unicode(13)),
     Column(’item_name’, Unicode(127)),
     Column(’item_number’, Unicode(127)),
     Column(’quantity’, Integer),
     Column(’payment_date’, Unicode(127)),
     Column(’payment_status’, Unicode(20)),
     Column(’payment_type’, Unicode(10)),
     Column(’pending_reason’, Unicode(20)),
     Column(’reason_code’, Unicode(20)),
     Column(’mc_currency’, Unicode(127)),
     Column(’mc_fee’, Unicode(127)),
     Column(’mc_gross’, Unicode(127)),
     Column(’txn_id’, Unicode(17)),


B.W. McAdams (Evil Monkey Labs)    Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   31 / 42
SQLAlchemy Model II
Paypal: OH THE HORROR




     Column(’address_name’, Unicode(255)),
     Column(’address_street’, Unicode(255)),
     Column(’address_city’, Unicode(255)),
     Column(’address_state’, Unicode(255)),
     Column(’address_zip’, Unicode(255)),
     Column(’address_country’, Unicode(255)),
     Column(’address_country_code’, Unicode(255)),
     Column(’address_status’, Unicode(15)),
     Column(’notes’, Unicode(255), nullable=True),
     mysql_engine=’InnoDB’
 )

 mapper(PaypalIPN, t_paypal_ipn)




B.W. McAdams (Evil Monkey Labs)    Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   32 / 42
MongoKit Model I
Admin

 class AdminUser(MongoPylonsDocument):
     use_autorefs = True
     use_dot_notation = True
     collection_name = ’admin_users’
     structure = {
         ’username’: unicode, # unique
         ’password’: unicode,
         ’display_name’: unicode,
         ’email’: unicode,
         ’last_ip’: unicode,
         ’last_login_date’: datetime.datetime,
         ’avatar’: unicode,
         ’disabled’: bool,
     }

    required_fields = [’username’, ’password’, ’email’]
    default_values = {’disabled’: False, ’last_login_date’: datetime.datetime.now()}

    indexes = [
        {
          ’fields’: [’username’, ’password’],
          ’ttl’: 86400
        },
        {
          ’fields’: [’password’],
          ’ttl’: 86400
        }
    ]


B.W. McAdams (Evil Monkey Labs)    Sluggy.com: MySQL to MongoDB     Mongo Boston - 9/20/10   33 / 42
MongoKit Model II
Admin




B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   34 / 42
MongoKit Model I
News

class NewsStory(MongoPylonsDocument):
    use_dot_notation = True
    use_autorefs = True
    collection_name = ’news’
    structure = {
        ’author’: AdminUser,
        ’headline’: unicode,
        ’story’: unicode,
        ’start_date’: datetime.datetime,
        ’end_date’: datetime.datetime,
        ’archived’: bool # default false
    }

    required_fields = [’author’, ’headline’, ’story’, ’start_date’]
    default_values = {
      ’start_date’: TODAY,
      ’archived’: False,
    }

    indexes = [
        {
            ’fields’: [’start_date’, ’end_date’],
            ’ttl’: 86400,
        },
        {
            ’fields’: ’archived’,
            ’ttl’: 86400,
        }


B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB        Mongo Boston - 9/20/10   35 / 42
MongoKit Model II
News




    ]




B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   36 / 42
MongoKit Model
PayPal: OH THE. . . that’s not so bad.




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   37 / 42
MongoKit Model I
PayPal: “Instead of using the ORM. . . ”




 ipn_db = None
 try:
     dbh = MongoPylonsEnv.mongo_conn()
         [MongoPylonsEnv.get_default_db()][’defenders_paypal_ipn’]
     ipn_id = dbh.insert(dict(request.POST.items()), safe=True)
     ipn_db = dbh.find_one({’_id’: ipn_id})
     if not ipn_db:
         raise Exception(’could not lookup, post-insert’)
 except Exception, e:
     log.exception("Paypal IPN Error: Unable to commit IPN data to "
                    " Database: %s " % repr(e))
     raise DefendersIPNException(repr(e))




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB        Mongo Boston - 9/20/10   38 / 42
MySQL -> Mongo Migration I
Admin Migration



 db = mongoModel.AdminUser._get_connection()
 conn = db.connection()
 conn.drop_database(’emergencyPants’)

 admins = {}
 for user in meta.Session.query(AdminUser).all():
     _admin = mongoModel.AdminUser(doc={
         ’username’: user.username,
         ’password’: user.password,
         ’avatar’: user.avatar,
         ’disabled’: user.disabled,
         ’display_name’: user.display_name,
         ’email’: user.email,
         ’last_ip’: unicode(user.last_ip),
         ’last_login_date’: user.last_login_date,
     }).save()
     admins[user.id] = _admin

 mongoModel.AdminUser.get_collection().ensure_index(’password’,
             direction=ASCENDING, unique=True)
 mongoModel.AdminUser.get_collection().ensure_index(
             [(’username’, ASCENDING),
             (’password’, ASCENDING)])




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   39 / 42
MySQL -> Mongo Migration I
News Migration




 print "Importing News Stories."
 for story in meta.Session.query(NewsStory).all():
     _story = mongoModel.NewsStory(doc={
         ’author’: admins[story.author_id],
         ’headline’: story.headline,
         ’story’: story.story,
         ’start_date’: convert_date(story.start_date),
         ’end_date’: convert_date(story.end_date),
         ’archived’: story.archive
     }).save()

 print "Setting up news story indices."
 mongoModel.NewsStory.get_collection().
     ensure_index(’archived’, direction=ASCENDING)
 mongoModel.NewsStory.get_collection().
     ensure_index([(’start_date’, ASCENDING),
                   (’end_date’, ASCENDING)])




 B.W. McAdams (Evil Monkey Labs)   Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   40 / 42
Looking for news I
In Mongo. . .




       Before, with MySQL/SQLAlchemy:
        def _get_news(date):
           news = meta.Session.query(NewsStory).
              filter(and_(NewsStory.archive==False, NewsStory.start_date<=date,
                     or_(NewsStory.end_date==None, NewsStory.end_date>date)))
                     .order_by(NewsStory.start_date.desc()).all()
            return news


       After, with MongoKit:
        def _get_news(date):
            news = NewsStory.all({
                ’archived’: False,
                ’start_date’: {’$lte’: c._today}
            }).where(’this.end_date == null || this.end_date >= new Date()’).
               sort(’start_date’, -1)

             return news




 B.W. McAdams (Evil Monkey Labs)    Sluggy.com: MySQL to MongoDB      Mongo Boston - 9/20/10   41 / 42
Questions?
Contact Info


       Contact Me
                twitter: @rit
                email: bwmcadams@gmail.com
                bitbucket: http://hg.evilmonkeylabs.net (For MongoKit &
                Beaker code)
                github: http://github.com/bwmcadams (Where most of my
                newer code lives)
       Pressing Questions?
                IRC - freenode.net #mongodb
                MongoDB Users List -
                http://groups.google.com/group/mongodb-user
       Mongo Python Language Center -
       http://api.mongodb.org/python/index.html (Tutorial, API Docs
       and links to third party toolkits)




 B.W. McAdams (Evil Monkey Labs)            Sluggy.com: MySQL to MongoDB   Mongo Boston - 9/20/10   42 / 42

More Related Content

Similar to MySQL to MongoDB @ Sluggy.com: MongoDB Boston, September 20, 2010

Lessons Learned Migrating 2+ Billion Documents at Craigslist
Lessons Learned Migrating 2+ Billion Documents at CraigslistLessons Learned Migrating 2+ Billion Documents at Craigslist
Lessons Learned Migrating 2+ Billion Documents at CraigslistJeremy Zawodny
 
Using RAG to create your own Podcast conversations.pdf
Using RAG to create your own Podcast conversations.pdfUsing RAG to create your own Podcast conversations.pdf
Using RAG to create your own Podcast conversations.pdfRichard Rodger
 
Clickhouse Capacity Planning for OLAP Workloads, Mik Kocikowski of CloudFlare
Clickhouse Capacity Planning for OLAP Workloads, Mik Kocikowski of CloudFlareClickhouse Capacity Planning for OLAP Workloads, Mik Kocikowski of CloudFlare
Clickhouse Capacity Planning for OLAP Workloads, Mik Kocikowski of CloudFlareAltinity Ltd
 
Infrastructure as code might be literally impossible part 2
Infrastructure as code might be literally impossible part 2Infrastructure as code might be literally impossible part 2
Infrastructure as code might be literally impossible part 2ice799
 
The Anatomy Of The Google Architecture Fina Lv1.1
The Anatomy Of The Google Architecture Fina Lv1.1The Anatomy Of The Google Architecture Fina Lv1.1
The Anatomy Of The Google Architecture Fina Lv1.1Hassy Veldstra
 
14 scaleabilty wics
14 scaleabilty wics14 scaleabilty wics
14 scaleabilty wicsashish61_scs
 
Regex Considered Harmful: Use Rosie Pattern Language Instead
Regex Considered Harmful: Use Rosie Pattern Language InsteadRegex Considered Harmful: Use Rosie Pattern Language Instead
Regex Considered Harmful: Use Rosie Pattern Language InsteadAll Things Open
 
Klmug presentation - Simple Analytics with MongoDB
Klmug presentation - Simple Analytics with MongoDBKlmug presentation - Simple Analytics with MongoDB
Klmug presentation - Simple Analytics with MongoDBRoss Affandy
 
Resilience: the key requirement of a [big] [data] architecture - StampedeCon...
Resilience: the key requirement of a [big] [data] architecture  - StampedeCon...Resilience: the key requirement of a [big] [data] architecture  - StampedeCon...
Resilience: the key requirement of a [big] [data] architecture - StampedeCon...StampedeCon
 
Mongodb beijingconf yottaa_3.3
Mongodb beijingconf yottaa_3.3Mongodb beijingconf yottaa_3.3
Mongodb beijingconf yottaa_3.3Yottaa
 
STP201 Efficiency at Scale - AWS re: Invent 2012
STP201 Efficiency at Scale - AWS re: Invent 2012STP201 Efficiency at Scale - AWS re: Invent 2012
STP201 Efficiency at Scale - AWS re: Invent 2012Amazon Web Services
 
Modern UI Development With Node.js
Modern UI Development With Node.jsModern UI Development With Node.js
Modern UI Development With Node.jsRyan Anklam
 
In-Memory Database Performance on AWS M4 Instances
In-Memory Database Performance on AWS M4 InstancesIn-Memory Database Performance on AWS M4 Instances
In-Memory Database Performance on AWS M4 InstancesSingleStore
 
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...MongoDB
 
MongoDB Tokyo - Monitoring and Queueing
MongoDB Tokyo - Monitoring and QueueingMongoDB Tokyo - Monitoring and Queueing
MongoDB Tokyo - Monitoring and QueueingBoxed Ice
 
MySQL Oslayer performace optimization
MySQL  Oslayer performace optimizationMySQL  Oslayer performace optimization
MySQL Oslayer performace optimizationLouis liu
 
MySQL Schema Design in Practice
MySQL Schema Design in PracticeMySQL Schema Design in Practice
MySQL Schema Design in PracticeJaime Crespo
 

Similar to MySQL to MongoDB @ Sluggy.com: MongoDB Boston, September 20, 2010 (20)

Lessons Learned Migrating 2+ Billion Documents at Craigslist
Lessons Learned Migrating 2+ Billion Documents at CraigslistLessons Learned Migrating 2+ Billion Documents at Craigslist
Lessons Learned Migrating 2+ Billion Documents at Craigslist
 
Using RAG to create your own Podcast conversations.pdf
Using RAG to create your own Podcast conversations.pdfUsing RAG to create your own Podcast conversations.pdf
Using RAG to create your own Podcast conversations.pdf
 
Clickhouse Capacity Planning for OLAP Workloads, Mik Kocikowski of CloudFlare
Clickhouse Capacity Planning for OLAP Workloads, Mik Kocikowski of CloudFlareClickhouse Capacity Planning for OLAP Workloads, Mik Kocikowski of CloudFlare
Clickhouse Capacity Planning for OLAP Workloads, Mik Kocikowski of CloudFlare
 
Infrastructure as code might be literally impossible part 2
Infrastructure as code might be literally impossible part 2Infrastructure as code might be literally impossible part 2
Infrastructure as code might be literally impossible part 2
 
The Anatomy Of The Google Architecture Fina Lv1.1
The Anatomy Of The Google Architecture Fina Lv1.1The Anatomy Of The Google Architecture Fina Lv1.1
The Anatomy Of The Google Architecture Fina Lv1.1
 
14 scaleabilty wics
14 scaleabilty wics14 scaleabilty wics
14 scaleabilty wics
 
Os Krug
Os KrugOs Krug
Os Krug
 
CQRS In An Hour Or So
CQRS In An Hour Or SoCQRS In An Hour Or So
CQRS In An Hour Or So
 
Regex Considered Harmful: Use Rosie Pattern Language Instead
Regex Considered Harmful: Use Rosie Pattern Language InsteadRegex Considered Harmful: Use Rosie Pattern Language Instead
Regex Considered Harmful: Use Rosie Pattern Language Instead
 
Klmug presentation - Simple Analytics with MongoDB
Klmug presentation - Simple Analytics with MongoDBKlmug presentation - Simple Analytics with MongoDB
Klmug presentation - Simple Analytics with MongoDB
 
Resilience: the key requirement of a [big] [data] architecture - StampedeCon...
Resilience: the key requirement of a [big] [data] architecture  - StampedeCon...Resilience: the key requirement of a [big] [data] architecture  - StampedeCon...
Resilience: the key requirement of a [big] [data] architecture - StampedeCon...
 
Mongodb beijingconf yottaa_3.3
Mongodb beijingconf yottaa_3.3Mongodb beijingconf yottaa_3.3
Mongodb beijingconf yottaa_3.3
 
STP201 Efficiency at Scale - AWS re: Invent 2012
STP201 Efficiency at Scale - AWS re: Invent 2012STP201 Efficiency at Scale - AWS re: Invent 2012
STP201 Efficiency at Scale - AWS re: Invent 2012
 
Modern UI Development With Node.js
Modern UI Development With Node.jsModern UI Development With Node.js
Modern UI Development With Node.js
 
In-Memory Database Performance on AWS M4 Instances
In-Memory Database Performance on AWS M4 InstancesIn-Memory Database Performance on AWS M4 Instances
In-Memory Database Performance on AWS M4 Instances
 
Triple Blitz Strike
Triple Blitz StrikeTriple Blitz Strike
Triple Blitz Strike
 
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
 
MongoDB Tokyo - Monitoring and Queueing
MongoDB Tokyo - Monitoring and QueueingMongoDB Tokyo - Monitoring and Queueing
MongoDB Tokyo - Monitoring and Queueing
 
MySQL Oslayer performace optimization
MySQL  Oslayer performace optimizationMySQL  Oslayer performace optimization
MySQL Oslayer performace optimization
 
MySQL Schema Design in Practice
MySQL Schema Design in PracticeMySQL Schema Design in Practice
MySQL Schema Design in Practice
 

Recently uploaded

Google I/O Extended 2024 Warsaw
Google I/O Extended 2024 WarsawGoogle I/O Extended 2024 Warsaw
Google I/O Extended 2024 WarsawGDSC PJATK
 
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdfIntroduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdfFIDO Alliance
 
AI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří KarpíšekAI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří KarpíšekCzechDreamin
 
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfThe Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfFIDO Alliance
 
What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024Stephanie Beckett
 
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...marcuskenyatta275
 
IESVE for Early Stage Design and Planning
IESVE for Early Stage Design and PlanningIESVE for Early Stage Design and Planning
IESVE for Early Stage Design and PlanningIES VE
 
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomSalesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomCzechDreamin
 
Using IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & IrelandUsing IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & IrelandIES VE
 
The Metaverse: Are We There Yet?
The  Metaverse:    Are   We  There  Yet?The  Metaverse:    Are   We  There  Yet?
The Metaverse: Are We There Yet?Mark Billinghurst
 
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Julian Hyde
 
Powerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara LaskowskaPowerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara LaskowskaCzechDreamin
 
How Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdf
How Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdfHow Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdf
How Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdfFIDO Alliance
 
Syngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdfSyngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdfSyngulon
 
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...FIDO Alliance
 
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeFree and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeCzechDreamin
 
Portal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russePortal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russe中 央社
 
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...FIDO Alliance
 
WebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceWebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceSamy Fodil
 
Intro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераIntro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераMark Opanasiuk
 

Recently uploaded (20)

Google I/O Extended 2024 Warsaw
Google I/O Extended 2024 WarsawGoogle I/O Extended 2024 Warsaw
Google I/O Extended 2024 Warsaw
 
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdfIntroduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
 
AI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří KarpíšekAI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří Karpíšek
 
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfThe Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
 
What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024What's New in Teams Calling, Meetings and Devices April 2024
What's New in Teams Calling, Meetings and Devices April 2024
 
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
TEST BANK For, Information Technology Project Management 9th Edition Kathy Sc...
 
IESVE for Early Stage Design and Planning
IESVE for Early Stage Design and PlanningIESVE for Early Stage Design and Planning
IESVE for Early Stage Design and Planning
 
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomSalesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
 
Using IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & IrelandUsing IESVE for Room Loads Analysis - UK & Ireland
Using IESVE for Room Loads Analysis - UK & Ireland
 
The Metaverse: Are We There Yet?
The  Metaverse:    Are   We  There  Yet?The  Metaverse:    Are   We  There  Yet?
The Metaverse: Are We There Yet?
 
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
 
Powerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara LaskowskaPowerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara Laskowska
 
How Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdf
How Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdfHow Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdf
How Red Hat Uses FDO in Device Lifecycle _ Costin and Vitaliy at Red Hat.pdf
 
Syngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdfSyngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdf
 
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
Choosing the Right FDO Deployment Model for Your Application _ Geoffrey at In...
 
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeFree and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
 
Portal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russePortal Kombat : extension du réseau de propagande russe
Portal Kombat : extension du réseau de propagande russe
 
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
FDO for Camera, Sensor and Networking Device – Commercial Solutions from VinC...
 
WebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM PerformanceWebAssembly is Key to Better LLM Performance
WebAssembly is Key to Better LLM Performance
 
Intro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераIntro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджера
 

MySQL to MongoDB @ Sluggy.com: MongoDB Boston, September 20, 2010

  • 1. Migrating from MySQL to MongoDB at Sluggy.com Brendan W. McAdams Evil Monkey Labs, LLC Mongo Boston Conference - Sep. 20, 2010 B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 1 / 42
  • 2. Outline 1 Introduction Basic Rundown Technology History 2 What We Learned Lessons Learned Over Time Open Source Code Yielded Why MongoDB? 3 Show Me The Code! The Old: MySQL Snippets 4 Final Items B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 2 / 42
  • 3. Outline 1 Introduction Basic Rundown Technology History 2 What We Learned Lessons Learned Over Time Open Source Code Yielded Why MongoDB? 3 Show Me The Code! The Old: MySQL Snippets 4 Final Items B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 3 / 42
  • 4. Sluggy.com Rundown Live since August 25, 1997 Updated Every Day (even if it’s just filler) More Users == More Load More Load == More Hardware On Advertising Revenues (e.g. Paying the Bills), Pete says: I tend to think of advertising as a finky spastic mentally retarded cat who sometimes wants to jump in my lap and other times wants to hiss at me and run for the litterbox and often walks in circles trying to figure out which of the two it wants, followed by dropping dead with a final thought..."ohhh! food!" Not Google... Not Trying to be Google. (Can’t afford to think or scale like Google. No dedicated staff or operations budget - advertising revenues cover server costs. Any downtime (be it bugs or system failure) means I get up at 3am to fix it. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 4 / 42
  • 5. Sluggy.com Rundown Live since August 25, 1997 Updated Every Day (even if it’s just filler) More Users == More Load More Load == More Hardware On Advertising Revenues (e.g. Paying the Bills), Pete says: I tend to think of advertising as a finky spastic mentally retarded cat who sometimes wants to jump in my lap and other times wants to hiss at me and run for the litterbox and often walks in circles trying to figure out which of the two it wants, followed by dropping dead with a final thought..."ohhh! food!" Not Google... Not Trying to be Google. (Can’t afford to think or scale like Google. No dedicated staff or operations budget - advertising revenues cover server costs. Any downtime (be it bugs or system failure) means I get up at 3am to fix it. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 4 / 42
  • 6. Sluggy.com Rundown Live since August 25, 1997 Updated Every Day (even if it’s just filler) More Users == More Load More Load == More Hardware On Advertising Revenues (e.g. Paying the Bills), Pete says: I tend to think of advertising as a finky spastic mentally retarded cat who sometimes wants to jump in my lap and other times wants to hiss at me and run for the litterbox and often walks in circles trying to figure out which of the two it wants, followed by dropping dead with a final thought..."ohhh! food!" Not Google... Not Trying to be Google. (Can’t afford to think or scale like Google. No dedicated staff or operations budget - advertising revenues cover server costs. Any downtime (be it bugs or system failure) means I get up at 3am to fix it. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 4 / 42
  • 7. Sluggy.com Rundown Some Stats 50GB/day (1.5TB of traffic/month on a single virtual box) 13 years of daily comics = 6500 image files (just for the comics) Artist is frequently late in updating. System has to handle random unexpected cache flushes & data updates. Erratic access behavior: Today’s comic is always popular and related load can be easily mitigated. However, archives may also be hit heavily by new readers or links from a newer strip to previous storylines. Hard to expect where in 6500+ strips people may be digging from day to day. “LUMP” Stack (Lighttpd, Ubuntu, MongoDB & Python) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 5 / 42
  • 8. Outline 1 Introduction Basic Rundown Technology History 2 What We Learned Lessons Learned Over Time Open Source Code Yielded Why MongoDB? 3 Show Me The Code! The Old: MySQL Snippets 4 Final Items B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 6 / 42
  • 9. Sluggy.com Technology History 1997 - 2000 August 25, 1997: Site Started, with basic code by Pete‘s friends/coworkers. Static HTML generated via midnight cron executing Perl. No dynamic content - Hand edited HTML for news, navigation, etc. File format requires globs: 000217a.gif 000217b.gif 000217c.gif All make up the panels for February 17, 2000. Artist likes & understands this format. Code looks for yyMMdd*.(gif|jpg) via glob and organizes them in order. 2000 - Original Developers split off and formed KeenSpot.com using same code & navigation concepts. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 7 / 42
  • 10. Sluggy.com Technology History 2002 Rewrite using MySQL & PHP (original goal: “No More HTML Editing”) Scope Creep == New Features. Dynamic headlines, news, predefined templates, dynamic navigation and a “Members Only Club”. First Folly - Reading MySQL and dynamically generating on each page request; Running dynamic code for essentially static content == FAIL. Disk I/O DoSing ... “call datacenter and cross fingers” Moved to smarty template caching, generating on-disk cache file upon first request (expires at midnight). Next 4 years became hellish with frequent Midnight crashes/failures as readers pound server for new comic. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 8 / 42
  • 11. Sluggy.com Technology History I 2006 Server move (For cost reasons) introduced new architecture problems Perceived cost savings pushed a move from SCSI/SAS disks to SATA Between template files & comic file globs. Disks couldn’t keep up. Implemented memcached to cache templates off-disk, in memory. Cached glob results (but not files). Cached anything else not likely to change - expiry set to a week (midnight for “index”) Sessions performed poorly in both disk and MySQL - caching in memcached helped. Apache began crushing memory & disk I/O. PHP isn’t thread safe; requires forked Apache workers (children are EXPENSIVE) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 9 / 42
  • 12. Sluggy.com Technology History II 2006 Migrated to Lighttpd + FastCGI - IO & RAM usage of webserver & PHP became negligible (Lots of tweaking of handling of static files esp. stat caching w/ FAM & good event handling): # without raising default fds (1024) we hit a lot of out of fds @ midnight # File descriptors include network connections *AND* filesystem handles... server.max-fds = 4096 # Use a well tuned event handler for connection handling server.event-handler = "linux-sysepoll" # Don’t shred the disk pulling static files; w/o a custom engine # like fam stat() runs for *EVERY* static file fetch. server.stat-cache-engine = "fam" # Severely limiting keep-alives paired w/ good Expires headers server.max-keep-alive-requests = 4 server.max-keep-alive-idle = 2 # Ask politely that browsers don’t keep redownloading static content expire.url = ( "/javascripts/" => "access 2 weeks", "/stylesheets/" => "access 2 weeks", "/icons/" => "access 2 weeks", "/images" => "access 1 weeks", "/images/comics/" => "access 1 days" ) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 10 / 42
  • 13. Sluggy.com Technology History 2009 Rewrote the system in Pylons (Python + SQLAlchemy[MySQL]) Integrated Beaker caching decorators (templates & code blocks) - simplified adding caching code at need. Clean ORM model, light & fast with lots of caching. Ran significantly better than on PHP - infinitely more tunable, sensible, and sane (Not necessarily a knock on PHP - but it was a 10 year old codebase). memcached continued to become a big, rickety crutch (cascading failure sucks) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 11 / 42
  • 14. Sluggy.com Technology History Aug. 2009 August 3, 2009: Pylons system (v1.0) Live with MySQL backend. Huge amounts of our code (as much as 80%) was dedicated to converting UI Objects to and from Database objects. WTF?... Most initial bugs occurred in this model <-> view layer. No more forking - Pylons & Python run threaded via SCGI (Similar to FastCGI). System resources significantly less taxed by the presentation stack. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 12 / 42
  • 15. Sluggy.com Technology History Aug. 2009 August 14, 2009: v1.10 Went Live - MySQL replaced by MongoDB (and MongoKit) Easy Migration - MongoKit was quickly dropped in place and queries adjusted to new model (Stuck to MySQL schema as much as possible) Maintained all bug fixes on MySQL branch for a few weeks “just in case” Performance vastly improved. Over next few months, built tools to use MongoDB in place of memcached for caching (mongodb_beaker) LAMP replaced by LUMP (Lighttpd, Ubuntu, MongoDB & Python) A few things left in memcached through a combination of “makes sense there” and indolence. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 13 / 42
  • 16. Sluggy.com Technology History Sept. 2009 MongoDB completely obviated dependency on dedicated Physical hardware; when a major issue with our ISP came up, migrated to Virtual hosting (slicehost) instead of Physical Hardware. Average system load is 0.05 on a 2G slice. MongoDB uses 1% of CPU on average. Switchover to MongoDB version took 2 minutes (ran data conversion script, deployed new code tag, bounced webserver / Pylons app) No downtime in any way attributable to MongoDB since go live - now live with MongoDB over a year. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 14 / 42
  • 17. Outline 1 Introduction Basic Rundown Technology History 2 What We Learned Lessons Learned Over Time Open Source Code Yielded Why MongoDB? 3 Show Me The Code! The Old: MySQL Snippets 4 Final Items B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 15 / 42
  • 18. memcached can rapidly become a crutch. . . meant to make up for RDBMS’ shortfalls but often masks other issues. . . memcached can be great for things you can afford to lose. It’s not just about what you “can’t afford to lose”. Beware of cascading failures. Over reliance can cause self-DoSing after a crash, reboot, accidental flush (even of just one keyset) etc... Lesson learned the hard way. See Coders at Work (Siebel) for a great discussion with its creator, Brian Fitzpatrick (founded LiveJournal & now a Google employee), about what led to memcached’s creation. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 16 / 42
  • 19. As long as I’m being hyperbolic. . . I MongoDB is a bionic leg replacement. . . MongoDB’s MMAP system gives you a “free” MRU cache. Done right and simple; caching on MongoDB is durable, light and fast. Significantly educes amount of scalability-glue code. No piles of special code manage caching; if it falls out of memory cache, it is still safely persisted to disk. The more you can put in memory, the less you beat on your disks. Especially important on virtual hosting: Be a Good Neighbor. But. . . don’t build your MongoDB system like a MySQL system (it’ll work, but you rapidly lose speed and flexibility) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 17 / 42
  • 20. As long as I’m being hyperbolic. . . II MongoDB is a bionic leg replacement. . . DBRefs should be used sparingly - favor embedded objects (don’t be afraid to denormalize and duplicate data); autorefs can be even worse as there’s a performance penalty imposed. Flexible schemas are good. Wasting your time mapping data back and forth between your presentation layer & RDBMS is not just tedious - it’s error prone. Object Mappers for MongoDB are fantastic tools but don’t overuse them - you take a huge flexibility & performance hit. Use field specifications, query operators, and atomic updates for maximum effectiveness. MongoDB excels at slicing out specific parts of a document - especially from embedded/nested fields. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 18 / 42
  • 21. Caveats While there is a lot “wrong” with our first pass implementation, MongoDB has been consistent, performant and most importantly: forgiving. Someone has to enforce a consistent schema - if it’s not your datastore (like a RDBMS does) then your code or ops people (or both) have to. The MongoDB community is vibrant, supportive and consistently brilliant. Use your community to build the best possible product. Corollary: If there is not a vibrant, supportive and intelligent community behind a product you are evaluating. . . run. Participate: A community that takes and never gives back cannot thrive. Sharing your knowledge and experience goes a long way. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 19 / 42
  • 22. Outline 1 Introduction Basic Rundown Technology History 2 What We Learned Lessons Learned Over Time Open Source Code Yielded Why MongoDB? 3 Show Me The Code! The Old: MySQL Snippets 4 Final Items B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 20 / 42
  • 23. Open Source Code I mongodb_beaker: Beaker Caching for MongoDB Open Source caching plugin for the Python Beaker stack. Uses distutils plugin entry points. Switching from memcached to Beaker + MongoDB required a 2 line config file change: - beaker.session.type = libmemcached - beaker.session.url = 127.0.0.1:11211 + beaker.session.type = mongodb + beaker.session.url = mongodb://localhost:27017/emergencyPants#sessions Lots of useful options in MongoDB Beaker. A few limitations on the beaker side which need changes in Beaker (manipulable cache data). Patch incubating for better replica, shard and master/slave support. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 21 / 42
  • 24. Open Source Code I MongoKit-Pylons: Pylons patches for Python MongORM Added support to MongoKit to run within a Pylons environment (threadlocal setup of connection pool) Adding a globally available thread safe connection pool to Pylon was simple. Add 2 lines to config/environment.py: from mongokit.ext.pylons_env import MongoPylonsEnv MongoPylonsEnv.init_mongo() B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 22 / 42
  • 25. Open Source Code II MongoKit-Pylons: Pylons patches for Python MongORM Added a few other features to simplify SQLAlchemy migration setattr / getattr support to allow mongoDoc.field instead of the dict interface (mongoDoc[’field’]) DB Authentication A few missing corners such as additional datatypes, enhanced index definitions on-document, group statement shortcuts, etc. Integrated support for autoreferences (which was/are mostly a very bad idea) Changes merged into MongoKit Trunk (MongoKit has stellar unit test coverage) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 23 / 42
  • 26. Outline 1 Introduction Basic Rundown Technology History 2 What We Learned Lessons Learned Over Time Open Source Code Yielded Why MongoDB? 3 Show Me The Code! The Old: MySQL Snippets 4 Final Items B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 24 / 42
  • 27. Why MongoDB? Dynamic Querying Flexibility (embedded documents, atomic updates, query operators and server-side javascript.) CouchDB’s approach appeared obtuse and rather unPythonic (not an indictment of CouchDB, simply reflective of my knowledge & opinion at the time) Tools like MongoKit allowed for easy replacement of existing MySQL ORM code with something almost identical FAST Great Support & Community Available. Core developers/founders have serious experience in real scalability, and are active in community. MongoDB Mailing List IRC: freenode.net #mongodb B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 25 / 42
  • 28. Outline 1 Introduction Basic Rundown Technology History 2 What We Learned Lessons Learned Over Time Open Source Code Yielded Why MongoDB? 3 Show Me The Code! The Old: MySQL Snippets 4 Final Items B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 26 / 42
  • 29. MySQL Schema Snippets I The Admin Table... CREATE TABLE ‘admin_users‘ ( ‘id‘ int(11) unsigned NOT NULL auto_increment, ‘username‘ varchar(45) collate latin1_general_ci NOT NULL default ’’, ‘password‘ char(32) collate latin1_general_ci NOT NULL, ‘display_name‘ varchar(64) collate latin1_general_ci default NULL, ‘email‘ varchar(255) collate latin1_general_ci NOT NULL default ’’, ‘avatar‘ varchar(255) collate latin1_general_ci default NULL, ‘last_ip‘ int(10) unsigned default NULL, ‘last_login_date‘ timestamp NOT NULL default ’0000-00-00 00:00:00’, ‘disabled‘ tinyint(1) default ’0’, PRIMARY KEY (‘id‘), UNIQUE KEY ‘UNIQUE‘ (‘username‘), UNIQUE KEY ‘admin_users_uniq‘ (‘email‘) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci PACK_KEYS=1; B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 27 / 42
  • 30. MySQL Schema Snippets I The News Table... CREATE TABLE ‘news‘ ( ‘id‘ int(11) unsigned NOT NULL auto_increment, ‘author_id‘ int(11) unsigned NOT NULL, ‘start_date‘ date NOT NULL, ‘end_date‘ date default NULL, ‘headline‘ varchar(255) NOT NULL, ‘story‘ text NOT NULL, ‘archive‘ tinyint(1) default ’0’, PRIMARY KEY (‘id‘), KEY ‘news_author‘ (‘author_id‘), CONSTRAINT ‘news_author‘ FOREIGN KEY (‘author_id‘) REFERENCES ‘admin_users‘ (‘id‘) ) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=latin1; B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 28 / 42
  • 31. SQLAlchemy Model I The Admin Object class AdminUser(ORMObject): pass t_admin_users = Table(’admin_users’, meta.metadata, Column(’id’, Integer, primary_key=True), Column(’username’, Unicode(45), nullable=False, unique=True), Column(’password’, Unicode(32), nullable=False), Column(’display_name’, Unicode(64)), # Should be unique? Column(’email’, Unicode(255), nullable=False, unique=True), Column(’last_ip’, IPV4Address, nullable=True), Column(’last_login_date’, MSTimeStamp, nullable=False), Column(’avatar’, Unicode(255), nullable=True), Column(’disabled’, Boolean, default=False), mysql_engine=’InnoDB’ ) mapper(AdminUser, t_admin_users) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 29 / 42
  • 32. SQLAlchemy Model I The News Object class NewsStory(ORMObject): pass t_news = Table(’news’, meta.metadata, Column(’id’, Integer, primary_key=True), Column(’author_id’, Integer, ForeignKey(’admin_users.id’), nullable=False), Column(’start_date’, Date, nullable=False), Column(’end_date’, Date), Column(’headline’, Unicode(255), nullable=False), Column(’story’, Unicode, nullable=False), Column(’archive’, Boolean, default=False), mysql_engine=’InnoDB’ ) mapper(NewsStory, t_news, properties={ ’author’: relation(AdminUser, backref=’news_stories’) }) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 30 / 42
  • 33. SQLAlchemy Model I Paypal: OH THE HORROR class PaypalIPN(ORMObject): pass t_paypal_ipn = Table(’paypal_ipn’, meta.metadata, Column(’id’, Integer, primary_key=True), Column(’first_name’, Unicode(64)), Column(’last_name’, Unicode(64)), Column(’payer_business_name’, Unicode(127)), Column(’payer_email’, Unicode(127)), Column(’payer_id’, Unicode(13)), Column(’payer_status’, Unicode(10)), Column(’residence_country’, Unicode(2)), Column(’business’, Unicode(127)), Column(’receiver_email’, Unicode(127)), Column(’receiver_id’, Unicode(13)), Column(’item_name’, Unicode(127)), Column(’item_number’, Unicode(127)), Column(’quantity’, Integer), Column(’payment_date’, Unicode(127)), Column(’payment_status’, Unicode(20)), Column(’payment_type’, Unicode(10)), Column(’pending_reason’, Unicode(20)), Column(’reason_code’, Unicode(20)), Column(’mc_currency’, Unicode(127)), Column(’mc_fee’, Unicode(127)), Column(’mc_gross’, Unicode(127)), Column(’txn_id’, Unicode(17)), B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 31 / 42
  • 34. SQLAlchemy Model II Paypal: OH THE HORROR Column(’address_name’, Unicode(255)), Column(’address_street’, Unicode(255)), Column(’address_city’, Unicode(255)), Column(’address_state’, Unicode(255)), Column(’address_zip’, Unicode(255)), Column(’address_country’, Unicode(255)), Column(’address_country_code’, Unicode(255)), Column(’address_status’, Unicode(15)), Column(’notes’, Unicode(255), nullable=True), mysql_engine=’InnoDB’ ) mapper(PaypalIPN, t_paypal_ipn) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 32 / 42
  • 35. MongoKit Model I Admin class AdminUser(MongoPylonsDocument): use_autorefs = True use_dot_notation = True collection_name = ’admin_users’ structure = { ’username’: unicode, # unique ’password’: unicode, ’display_name’: unicode, ’email’: unicode, ’last_ip’: unicode, ’last_login_date’: datetime.datetime, ’avatar’: unicode, ’disabled’: bool, } required_fields = [’username’, ’password’, ’email’] default_values = {’disabled’: False, ’last_login_date’: datetime.datetime.now()} indexes = [ { ’fields’: [’username’, ’password’], ’ttl’: 86400 }, { ’fields’: [’password’], ’ttl’: 86400 } ] B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 33 / 42
  • 36. MongoKit Model II Admin B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 34 / 42
  • 37. MongoKit Model I News class NewsStory(MongoPylonsDocument): use_dot_notation = True use_autorefs = True collection_name = ’news’ structure = { ’author’: AdminUser, ’headline’: unicode, ’story’: unicode, ’start_date’: datetime.datetime, ’end_date’: datetime.datetime, ’archived’: bool # default false } required_fields = [’author’, ’headline’, ’story’, ’start_date’] default_values = { ’start_date’: TODAY, ’archived’: False, } indexes = [ { ’fields’: [’start_date’, ’end_date’], ’ttl’: 86400, }, { ’fields’: ’archived’, ’ttl’: 86400, } B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 35 / 42
  • 38. MongoKit Model II News ] B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 36 / 42
  • 39. MongoKit Model PayPal: OH THE. . . that’s not so bad. B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 37 / 42
  • 40. MongoKit Model I PayPal: “Instead of using the ORM. . . ” ipn_db = None try: dbh = MongoPylonsEnv.mongo_conn() [MongoPylonsEnv.get_default_db()][’defenders_paypal_ipn’] ipn_id = dbh.insert(dict(request.POST.items()), safe=True) ipn_db = dbh.find_one({’_id’: ipn_id}) if not ipn_db: raise Exception(’could not lookup, post-insert’) except Exception, e: log.exception("Paypal IPN Error: Unable to commit IPN data to " " Database: %s " % repr(e)) raise DefendersIPNException(repr(e)) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 38 / 42
  • 41. MySQL -> Mongo Migration I Admin Migration db = mongoModel.AdminUser._get_connection() conn = db.connection() conn.drop_database(’emergencyPants’) admins = {} for user in meta.Session.query(AdminUser).all(): _admin = mongoModel.AdminUser(doc={ ’username’: user.username, ’password’: user.password, ’avatar’: user.avatar, ’disabled’: user.disabled, ’display_name’: user.display_name, ’email’: user.email, ’last_ip’: unicode(user.last_ip), ’last_login_date’: user.last_login_date, }).save() admins[user.id] = _admin mongoModel.AdminUser.get_collection().ensure_index(’password’, direction=ASCENDING, unique=True) mongoModel.AdminUser.get_collection().ensure_index( [(’username’, ASCENDING), (’password’, ASCENDING)]) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 39 / 42
  • 42. MySQL -> Mongo Migration I News Migration print "Importing News Stories." for story in meta.Session.query(NewsStory).all(): _story = mongoModel.NewsStory(doc={ ’author’: admins[story.author_id], ’headline’: story.headline, ’story’: story.story, ’start_date’: convert_date(story.start_date), ’end_date’: convert_date(story.end_date), ’archived’: story.archive }).save() print "Setting up news story indices." mongoModel.NewsStory.get_collection(). ensure_index(’archived’, direction=ASCENDING) mongoModel.NewsStory.get_collection(). ensure_index([(’start_date’, ASCENDING), (’end_date’, ASCENDING)]) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 40 / 42
  • 43. Looking for news I In Mongo. . . Before, with MySQL/SQLAlchemy: def _get_news(date): news = meta.Session.query(NewsStory). filter(and_(NewsStory.archive==False, NewsStory.start_date<=date, or_(NewsStory.end_date==None, NewsStory.end_date>date))) .order_by(NewsStory.start_date.desc()).all() return news After, with MongoKit: def _get_news(date): news = NewsStory.all({ ’archived’: False, ’start_date’: {’$lte’: c._today} }).where(’this.end_date == null || this.end_date >= new Date()’). sort(’start_date’, -1) return news B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 41 / 42
  • 44. Questions? Contact Info Contact Me twitter: @rit email: bwmcadams@gmail.com bitbucket: http://hg.evilmonkeylabs.net (For MongoKit & Beaker code) github: http://github.com/bwmcadams (Where most of my newer code lives) Pressing Questions? IRC - freenode.net #mongodb MongoDB Users List - http://groups.google.com/group/mongodb-user Mongo Python Language Center - http://api.mongodb.org/python/index.html (Tutorial, API Docs and links to third party toolkits) B.W. McAdams (Evil Monkey Labs) Sluggy.com: MySQL to MongoDB Mongo Boston - 9/20/10 42 / 42