<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lau-Labs</title>
	<atom:link href="http://labs.laulima.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://labs.laulima.com</link>
	<description>Developing Interactive Geo-Social Solutions Relevant to Life&#039;s Endeavours</description>
	<lastBuildDate>Wed, 26 Oct 2011 10:32:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Finding my gSpot &#8211; Continued Adventures with Geo-Location &amp; mongoDB</title>
		<link>http://labs.laulima.com/finding-my-gspot-geolocation-mongodb/</link>
		<comments>http://labs.laulima.com/finding-my-gspot-geolocation-mongodb/#comments</comments>
		<pubDate>Wed, 26 Oct 2011 10:32:24 +0000</pubDate>
		<dc:creator>Mark Smalley</dc:creator>
				<category><![CDATA[Geo-Location]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://labs.laulima.com/?p=250</guid>
		<description><![CDATA[I&#8217;ve finally found my gSpot. Not only as a developer, designer and passionate OpenSource advocate, but as a human too. I know my limits, and as a full time partner at Laulima, father and husband, I&#8217;ve also come to accept that I am incapable of giving back to the community as much as I would [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align:justify">
<p>I&#8217;ve finally found my <strong>gSpot</strong>. Not only as a developer, designer and passionate OpenSource advocate, but as a human too. I know my limits, and as a full time partner at Laulima, father and husband, I&#8217;ve also come to accept that I am incapable of giving back to the community as much as I would like. I was once a self-proclaimed BuddyPress fanatic and had grand plans for <a href="http://gpress.my">gPress</a>, which was my first foray into providing freely distributed OpenSource geo-location tools. Prior to that, I had worked with a &#8220;premium&#8221; theme company creating commercial geo-location themes, and was originally brought on at Laulima to provide additional geo-location services to <a href="http://travelblog.org">TravelBlog</a>.</p>
<p>Unfortunately, with all that time previously spent in Google Maps and jQuery, I had never spent the time creating a proper plugin. I would usually cobble things together with some copy, pasting and repeated tweaking. I&#8217;d also started introducing marker clustering and customized HTML / CSS3 InfoWindows through a collection of other external odds and ends that was quickly growing into a complete unmanageable mess. That stops here!</p>
<p>I&#8217;ve now developed a jQuery plugin called <a href="http://gspot.smalley.my">gSpot</a>, from which all future browser-based geo-location work I do will be extended. I&#8217;ve also embraced <a href="http://github.com/msmalley">GitHub</a>, from where I will be distributing all future OpenSource work that I personally develop. Speaking of which, I&#8217;ve also managed to convince Laulima to start using <a href="https://github.com/MongoPress/">GitHub</a>, from where we will be distributing <a href="https://github.com/MongoPress/mongoBase">mongoBase</a>.</p>
<p>For those that don&#8217;t already know, Laulima is developing it&#8217;s own OpenSource CMS called <a href="http://mongopress.org">MongoPress</a>, which is a <a href="http://mongodb.org">mongoDB</a> powered platform providing high-performance NoSQL web-management. The underlying CMS is freely available from MongoPress.org as a self-hosted download. Laulima are ultimately planning to commercialize MongoPress.com by launching a hosted version of the system with an integrated &#8220;verified&#8221; app-store. This fully-managed hosted phase of Laulima&#8217;s plans is currently in an invite-only state, and was pushed forward ahead of schedule specifically for the <a href="http://aws2011.mongopress.com">AWS Startup Challenge</a> that we recently participated in. However, as outlined within our official <a href="http://trac.mongopress.org/trac/report/3">roadmap</a>, the true focus of Laulima&#8217;s current efforts are concentrating on a 0.3 release.</p>
<p>MongoPress 0.3 will be our biggest update to date, a complete re-write from the ground-up, and rather than simply make a rock-solid OOP compliant core strictly for MongoPress, we decided to take things one step further by developing a core foundation and set of modules that would work for any application developed for mongoDB. It&#8217;s no secret that we have fallen for mongoDB. Truth be known, we&#8217;re head-over heals, or at least I am. There&#8217;s no turning back for me and Laulima is committed to the point of organizing Malaysia&#8217;s first and only official <a href="http://lauli.ma/klmug">MongoDB User Group</a>. In fact, I&#8217;d even go as far as saying that mongoDB is partly responsible for me finding my gSpot, for it allows me to develop at such a rapid pace whilst keeping all my logic contained within a single language. Nonetheless, this development is not rapid enough for my liking, which is why I have pushed so hard for mongoBase to get such prominence within our current work-flow.</p>
<p>As a user of <a href="http://backpress.org">Automattic&#8217;s BackPress</a>, from which I was just about capable of getting <a href="http://geopress.my">GeoPress</a> launched, I quickly realized the importance of a solid framework. But unlike the mess that is BackPress, which appears to have been cobbled together by working backwards and extracting things from core, I wanted to do things right with MongoPress. It is for this reason that mongoBase has now become our top priority. MongoBase will be the foundation for MongoPress, which is why everything is being completely re-written for the 0.3 release. We want a foundation at core that has been specifically built as a foundation, which can be used for anything from a simple one page prototypes for visualizing new mongoDB based ideas, through to fully realized CMS platforms and everything in-between.</p>
<p>When I get an idea, which come more often than I can handle, I&#8217;d like to be able to more easily develop those ideas, which is why I am now so focused on foundations. It is with these foundations that I am also working on my most ambitious project to date, which is currently codenamed &#8221; <a href="http://www.mongomail.org">MongoMail</a> &#8221; and is my attempt to put an end to IMAP and POP3 emailing systems with a long-term vision that would take me a million more hours than I have freely available in my spare time. It&#8217;s a project so grand in scale that I would have been crazy to even think about starting it&#8230; It&#8217;s also a project that I started several weekends ago&#8230;</p>
<p>Replacing the antiquated technologies currently known as email may seem impossible to some, and probably would be if the first stage of that unfathomable quest did not support IMAP (the underlying technology central to gMail, Microsoft Exchange and other such platforms). It would after all be illogical to assume you could completely replace the most used form of online communication with another form of communication that did not support the current form, which is why I am a man on a mission with a million and one things left to do&#8230;</p>
<p>So with that said and done, you might be asking where I currently stand&#8230;?</p>
<p>Well, I have at least made a start, without which, nothing would ever happen&#8230;</p>
<p>I already have a web-based PHP / mongoDB driven email client that can sync with IMAP and can be fully customized through themes and plugins. I have a default theme for this email client that revolutionizes the way we look at emails by threading conversations and auto-generating media galleries from attachments. Everything is asynchronous, AJAX powered and breathtakingly simple in the sexiest of minimal and mobile compatible ways.</p>
<p>We also posted a couple of images on <a href="http://twitter.com/mongomail">Twitter</a> today, where you can now get a quick glimpse of the working copy I am using from my localhost and take a peep at our <a href="http://twitter.com/mongomail/status/129129308072583169/photo/1">re-invented inbox</a> or how one <a href="http://twitter.com/mongomail/status/129129595042664448/photo/1">forwards messages</a> of the future&#8230; I say &#8220;we&#8221; because Laulima has graciously allowed me to spend a certain amount of my time continuing to develop the MongoMail project and can see the <strong>game-changing</strong> potential of this new territory. With that said, and due to Laulima&#8217;s insatiable commitment to the OpenSource community, phase one of this ambitious project will hopefully be available for download before the end of the year!</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://labs.laulima.com/finding-my-gspot-geolocation-mongodb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MongoPress 0.2.2 &#8211; More AJAX &amp; Better Mobility</title>
		<link>http://labs.laulima.com/mongopress-ajax-mobility/</link>
		<comments>http://labs.laulima.com/mongopress-ajax-mobility/#comments</comments>
		<pubDate>Wed, 14 Sep 2011 09:18:18 +0000</pubDate>
		<dc:creator>Mark Smalley</dc:creator>
				<category><![CDATA[MongoPress]]></category>

		<guid isPermaLink="false">http://labs.laulima.com/?p=204</guid>
		<description><![CDATA[MongoPress 0.2.2 is live! &#8211; http://mongopress.org Having made it through the 0.2 series in one piece, we are finally ready to start our most gruelling release cycle yet &#8211; the 0.3 series will see us returning to core and completely re-writing many of the core functions in an effort to drastically improve performance, stability and [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align:justify">
<p>MongoPress 0.2.2 is live! &#8211; <a href="http://mongopress.org">http://mongopress.org</a></p>
<p>Having made it through the 0.2 series in one piece, we are finally ready to start our most gruelling release cycle yet &#8211; the <a href="http://trac.mongopress.org/trac/query?status=new&amp;status=assigned&amp;status=reopened&amp;milestone=0.3+-+plugins">0.3 series</a> will see us returning to core and completely re-writing many of the core functions in an effort to drastically improve performance, stability and especially the way in which plugins and inherent caching is handled, but until then, we are hoping the <a href="http://trac.mongopress.org/trac/query?status=closed&amp;milestone=0.2.2">0.2.2 changes</a> will keep you interested.</p>
<p>With new style-sheets for hand-held devices and administration pages, along with print-only style-sheets for themes, my favourite new set of features for this release are the advance AJAX fetchers included in core, where you need only provide elements with specific classes (currently supporting fetch-feed, fetch-avatar and fetch-content), which when also given the relevant data-attributes; MongoPress will then perform AJAX requests to collect content and pump it into the selected container. Very cool stuff indeed &#8211; and as such, we have even updated the default theme included in core to show how this works &#8211; where AJAX is now used to collect the first featured-article and display it on the homepage as seen at &#8211; <a href="http://mongopress.org">http://mongopress.org</a></p>
<p>On a more personal note, I&#8217;m really happy to see we now have an AJAX-powered core-contributor / credits page in place &#8211; not because it has my name on it, but because it contains our first public contributor &#8211; <a href="http://twitter.com/dattas">Dattas</a> &#8211; thanks again for your input!</p>
<p>During this release cycle, we also held our first <a href="http://lauli.ma/klmug">Kuala-Lumpur MongoDB User-Group</a>, for which we conducted a rather thorough series of benchmarks aimed specifically at re-creating the environment of a CMS system, which was recently published here on the labs &#8211; <a href="http://labs.laulima.com/mongodb-vs-mysql-performance-benchmarks-cms">http://labs.laulima.com/mongodb-vs-mysql-performance-benchmarks-cms</a> &#8211; this clearly shows that our efforts with MongoPress have not been in vein and that any website or web-application with more than one simultaneous user and (or) visitor is going to benefit from the performance that MongoDB is able to offer, and that&#8217;s not even considering other important native functionality such as replica-sets, sharding, GridFS and geo-location!</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://labs.laulima.com/mongopress-ajax-mobility/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MongoDB Vs MySQL &#8211; Benchmarks Re-Creating Typical CMS Functionality to Compare Performance of MySQL and MongoDB in PHP / Apache</title>
		<link>http://labs.laulima.com/mongodb-vs-mysql-performance-benchmarks-cms/</link>
		<comments>http://labs.laulima.com/mongodb-vs-mysql-performance-benchmarks-cms/#comments</comments>
		<pubDate>Wed, 14 Sep 2011 05:21:24 +0000</pubDate>
		<dc:creator>Mark Smalley</dc:creator>
				<category><![CDATA[Benchmarks]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://labs.laulima.com/?p=213</guid>
		<description><![CDATA[Over the past few years there has been a gradual rise in prominence for a new breed of databases that is quickly gaining traction. NoSQL databases offer many advantages to developers over traditional Relational SQL databases, both in terms of development flexibility and the speed and instant scalability. The question that will be forefront in [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align:justify">
<p>Over the past few years there has been a gradual rise in prominence for a new breed of databases that is quickly gaining traction. NoSQL databases offer many advantages to developers over traditional Relational SQL databases, both in terms of development flexibility and the speed and instant scalability. The question that will be forefront in the mind of any developer working on a large project is &#8220;how does it perform?&#8221;. The bottom line for many projects will be &#8220;which database will run my application the best&#8221; &#8211; we at <a href="http://laulima.com">Laulima</a> also had these questions, and after an extensive but not exhaustive search failed to find any definitive third-party statistics for the simple tasks.</p>
<p><a href="http://laulima.com">Laulima</a> is responsible for the technology and design of two high profile projects, <a href="http://www.travelblog.org/">http://www.travelblog.org/</a> is a PHP MySQL based travel CMS, and <a href="http://www.travelblog.org/">http://www.mongopress.org/</a> is a new MongoDB (NoSQL) PHP OpenSource CMS &#8211; so our immediate interest was in measuring the performance on these two specific databases. Both <a href="http://mysql.com">MySQL</a> and <a href="http://mongodb.com">mongoDB</a> are open-source, are also both considered to be the standard of their classes.</p>
<p>And so in light of hosting the first-ever <a href="http://lauli.ma/klmug">Kuala-Lumpur MongoDB User-Group</a>, we wanted to present some easy to understand, realistic benchmarks for typical tasks that are usually associated with CMS platforms and how they might construct a page or interact with their users from a database-level.</p>
<h4>Deciding on Typical CMS Usage Scenarios</h4>
<p>With our experience developing <a href="http://travelblog.org">TravelBlog</a>, we have seen a single page require as many as 200 separate transactions to generate a page. This is admittedly a large number, and through the use of caching we have reduced this number down to a level where visitors rarely notice a pause. However, with a need to choose a benchmarking figure we selected this as our typical worst case &#8220;social-network&#8221; style page load. Analysing the typical number of reads Vs update operations, we opted for a ratio with 10 reads Vs 1 update.</p>
<p>Our benchmarks have used these numbers and ratios as the basis, they are not arbitrary but may differ from other less &#8220;heavy&#8221; CMS systems &#8211; we have also <a href="http://laulima.com/downloads/benchmark-scripts-001.zip">open-sourced</a> our scripts and encourage those interested to <a href="http://laulima.com/downloads/benchmark-scripts-001.zip">download</a> and adjust the parameters and server set-up as required. We are well aware that in specific usage scenarios, the results found could be very different.</p>
<h4>Breaking Down Typical CMS Operations</h4>
<p>NoSQL operates in a different way to SQL &#8211; where some of the operations that are fundamental to SQL are not the same in NoSQL. For instance; auto-incremented IDs and the fetching of random data do not make sense from a technical perspective in a NoSQL environment, and so the operations we simulated include:</p>
<ul>
<li><strong>MySQL:</strong> Select &#8211; Update &#8211; Insert &#8211; Delete</li>
<li><strong>MongoDB:</strong> Find &#8211; FindAndModify &#8211; Save &#8211; Remove</li>
</ul>
<p>We will randomly loop-through the PHP functions, meaning that certain functions will be called more than the others but the difference is is only in the region of 5%. We have taken high-profile website operations as the example, with lots of reads and select operations because the users and visitors are rarely inserting and updating data in comparison. We conducted the benchmarks using this operation in mind and both scripts have a query to run selects based on indexed column / fields, where no index but the index field will be run more than 5 consecutive times. All selects, updates and delete queries are based on random &#8220;lorem ipsum&#8221; data collected from an external text file.</p>
<h4>Ensuring Fairness</h4>
<p>We wrote our scripts in PHP, the language of nearly all our projects and 75% of all production websites (<a href="http://en.wikipedia.org/wiki/PHP#Usage">http://en.wikipedia.org/wiki/PHP#Usage</a>). We used Apache/2.2.9 (Debian), PHP Version 5.2.6-1+lenny13 from Debian Lenny package manager, MongoDB 1.8.2, MySQL 5.0+ with MongoDB driver version 1.2.4 from pecl, MySQL client API driver version 5.0.51a and Apache Bench (ab) in order to conduct our benchmarks concurrently. We stripped down our scripts to use the most commonly used drivers for each database, did not include any additional third-party frameworks, and as such error handling was also minimized. These are scripts intended purely for determining performance, and should not be used as the basis of an application.</p>
<p>In both cases we were not only measuring the pure performance of the database, but were also looking at the overhead from PHP and Apache, but seeing as both set-ups are identical, and both are industry standards, we feel that the impact of this is fair on the tested databases. The differences in the performance of the scripts should be a result of the database alone and so to ensure this, each benchmark run was conducted on a clean boot-up, through the localhost address (so that network issues would not impact performance) and no PHP code optimizer (eaccelerator, apc, xcache) was installed. Both databases saved their data in XFS partitions to get the best performance and no applications other than those used for the benchmarks were in use.</p>
<h4>Our Server</h4>
<p>Our server utilised the following specifications:</p>
<ul>
<li>Linux Debian Lenny Kernel 2.6.26-2-amd64</li>
<li>Intel(R) Core(TM) i5 CPU 661  @ 3.33GHz</li>
<li>4GB RAM</li>
<li>HDD SATA Model Number: WDC WD5000AADS-00S9B0 (500GB)</li>
</ul>
<p>This is a relatively new desktop workstation that we dual boot into a Linux server for cases like this. Unfortunately, we did not have the resources to test on a production level server (12 core, 16gb Linux servers in most cases) &#8211; but we anticipate that the levels of performance would hold true assuming that they were configured correctly.</p>
<h4>The Results</h4>
<p style="font-weight:bold">This first graph shows MongoDB under-performing when given only a single task to do at a time:</p>
<div class="iframe-wrapper" style="padding-bottom:25px">
  <iframe src="http://www.mongopress.org/presentations/benchmarks/mongodb-vs-mysql-01.html" scrolling="no" frameborder="0" style="height:625px;width:100%;">Please upgrade your browser</iframe>
</div>
<p style="font-weight:bold">But when MongoDB is given simultaneous connections and tasks, thinks become interesting:</p>
<div class="iframe-wrapper" style="padding-bottom:25px">
  <iframe src="http://www.mongopress.org/presentations/benchmarks/mongodb-vs-mysql-02.html" scrolling="no" frameborder="0" style="height:625px;width:100%;">Please upgrade your browser</iframe>
</div>
<h4>Concluding Thoughts</h4>
<p><strong>The full logs for these benchmarks can be seen at &#8211; <a href="http://www.mongopress.org/presentations/benchmarks/benchmark_results_001.txt">http://www.mongopress.org/presentations/benchmarks/benchmark_results_001.txt</a></strong></p>
<p>So forgetting about other MongoDB golden-nuggets, such as Replica-Sets, Sharding, GridFS and Geo-Location, not to mention the inherently relevant way of storing data as documents whilst providing developers with more native ways to easily extend the database and in-turn allow for more rapid development; <a href="http://mongodb.com">MongoDB</a> clearly outperforms MySQL at even the simplest of tasks when given simultaneous connectivity, which is something every web-site and or web-based application should strive to need.</p>
<p>You may also be interested in <a href="http://labs.laulima.com/how-to-import-7-million-locations-from-geonames-to-mysql-then-into-mongodb-so-they-be-compared-and-optimized-for-location-queries/">How To: Import 7 Million Locations from GeoNames to MySQL, then into MongoDB so they can be compared and optimized for Location Queries</a>.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://labs.laulima.com/mongodb-vs-mysql-performance-benchmarks-cms/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>MongoPress 0.2.1 &#8211; A minor release with major improvements!</title>
		<link>http://labs.laulima.com/mongopress-0-2-1-a-minor-release-with-major-improvements/</link>
		<comments>http://labs.laulima.com/mongopress-0-2-1-a-minor-release-with-major-improvements/#comments</comments>
		<pubDate>Thu, 08 Sep 2011 05:22:23 +0000</pubDate>
		<dc:creator>Mark Smalley</dc:creator>
				<category><![CDATA[MongoPress]]></category>

		<guid isPermaLink="false">http://labs.laulima.com/?p=198</guid>
		<description><![CDATA[Version 0.2.1 features a critical fix for AJAX powered admin-pages, as well as a whole bunch of other minor improvements as listed in the following change-set &#8211; http://trac.mongopress.org/trac/query?status=closed&#38;milestone=0.2.1. We&#8217;ve also released two public themes &#8211; http://svn.mongopress.org/themes/ &#8211; mongotope (live demo) and mongollery (live demo). With the first Kuala Lumpur MongoDB User Group now over, we [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align:justify">
<p>Version 0.2.1 features a critical fix for AJAX powered admin-pages, as well as a whole bunch of other minor improvements as listed in the following change-set &#8211; <a href="http://trac.mongopress.org/trac/query?status=closed&amp;milestone=0.2.1">http://trac.mongopress.org/trac/query?status=closed&amp;milestone=0.2.1</a>. We&#8217;ve also released two public themes &#8211; <a href="http://svn.mongopress.org/themes">http://svn.mongopress.org/themes/</a> &#8211; mongotope (<a href="http://www.smalley.my">live demo</a>) and mongollery (<a href="http://www.smalley.my/gallery/">live demo</a>). With the first <a href="http://lauli.ma/klmug">Kuala Lumpur MongoDB User Group</a> now over, we can also provide links to a couple of MongoPress-powered presentations (that use another theme we will soon be releasing). This includes <a href="http://lauli.ma/mdb001">Introducing MongoDB</a> and <a href="http://lauli.ma/mpp001">Introducing MongoPress</a>.</p>
<p>Our focus for the next release will be tying off a few loose ends prior to starting on our next major release. In 0.3 we plan to radically re-write most of core &#8211; specifically plugins and the way that web-pages are created from objects &#8211; 0.3 is going to be a solid bone-crunching release that will surely cement our platform with the necessary foundations for our <a href="http://trac.mongopress.org/trac/report/3">future</a>.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://labs.laulima.com/mongopress-0-2-1-a-minor-release-with-major-improvements/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>KLMUG #1 &#8211; The First Kuala-Lumpur MongoDB User Group</title>
		<link>http://labs.laulima.com/klmug-1-kuala-lumpur-mongodb-user-group/</link>
		<comments>http://labs.laulima.com/klmug-1-kuala-lumpur-mongodb-user-group/#comments</comments>
		<pubDate>Thu, 08 Sep 2011 02:56:22 +0000</pubDate>
		<dc:creator>Mark Smalley</dc:creator>
				<category><![CDATA[KL MUG]]></category>
		<category><![CDATA[MongoDB]]></category>

		<guid isPermaLink="false">http://labs.laulima.com/?p=185</guid>
		<description><![CDATA[We hosted KL MUG #1 (our first MongoDB user-group) last night, which was generously sponsored by 10gen, the company behind MongoDB. Not only was it our first user-group, it was also the first time our company have hosted any form of public gathering &#8211; and to make things even more nerve-racking, it was also the [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align:justify">
<p>We hosted <a href="http://lauli.ma/klmug">KL MUG</a> #1 (our first MongoDB user-group) last night, which was generously sponsored by <a href="http://10gen.com">10gen</a>, the company behind <a href="http://mongodb.com">MongoDB</a>. Not only was it our first user-group, it was also the first time our company have hosted any form of public gathering &#8211; and to make things even more nerve-racking, it was also the first time I planned to give a presentation.</p>
<h4 style="text-align:center">Introducing MongoDB &amp; Why I Love it!</h4>
<p><a href="http://www.mongopress.org/presentations/mongodb-001/"><img src="http://www.mongopress.org/presentations/mongodb-001/mp-content/themes/presentations/images/temp_mongodb/mongodb_cover.jpg" /></a></p>
<p>The presentation featured above is powered by <a href="http://mongopress.org">MongoPress</a> and will soon be added to our public repository of themes, along with <a href="http://www.smalley.my">mongotope</a> and <a href="http://smalley.my/gallery/">mongollery</a> &#8211; which are already available to download via SVN &#8211; <a href="http://svn.mongopress.org/themes/">http://svn.mongopress.org/themes/</a></p>
<p>Getting back to the topic at hand &#8211; I was somewhat surprised that anyone made it &#8211; especially with it being the first one &#8211; so really, thanks ever so much for coming and showing so much excitement for the coming months &#8211; for all those skeptics out there &#8211; the proof is in the pudding &#8211; so here goes:</p>
<p><a href="http://www.meetup.com/KL-MongoDB-User-Group/photos/3246872/"><img src="http://photos2.meetupstatic.com/photos/event/9/9/f/e/600_54099422.jpeg" /></a></p>
<p>We spent the first hour sitting in a circle getting to know each other and eating some damn fine <a href="http://www.yellowcabpizza.com/">pizza</a>, after which, I presented a quick introduction to MongoDB which focused on the reasons why I (as a front-end designer / developer who should hate all things administrative and databasey) love it so much &#8211; <a href="http://twitter.com/ali_watters">Ali</a> then took centre stage and provided a live hands-on session where he set-up an instance on Amazon EC2 and got the latest mongo drivers installed and ready to rock. We then discussed potential topics for next month, which included an interest in replica-sets and sharding, NodeJS and MongoDB as well as streaming video and audio with GridFS.</p>
<p>Please do join the Meet-Up group &#8211; <a href="http://www.meetup.com/KL-MongoDB-User-Group/">http://www.meetup.com/KL-MongoDB-User-Group/</a>, which is the preferred method that 10gen have asked us to organise things through &#8211; so until next time; may the force be with you! : -)</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://labs.laulima.com/klmug-1-kuala-lumpur-mongodb-user-group/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MongoDB as CMS achieved &#8211; Re-Introducing MongoPress 0.2</title>
		<link>http://labs.laulima.com/mongodb-cms-mongopress/</link>
		<comments>http://labs.laulima.com/mongodb-cms-mongopress/#comments</comments>
		<pubDate>Fri, 26 Aug 2011 09:36:49 +0000</pubDate>
		<dc:creator>Mark Smalley</dc:creator>
				<category><![CDATA[MongoPress]]></category>

		<guid isPermaLink="false">http://labs.laulima.com/?p=172</guid>
		<description><![CDATA[Well folks, it&#8217;s been a real interesting and somewhat intense couple of weeks&#8230; Around the same time as winning the monthly developer contest at 10gen, I started work on a new administration interface for MongoPress whilst Ali set himself on the task of re-writing the installation process and better organising the general flow of perma-trail [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align: justify">
<p>Well folks, it&#8217;s been a real interesting and somewhat intense couple of weeks&#8230;</p>
<p>Around the same time as winning the monthly <a href="http://twitter.com/#!/10gen/status/101724152888688640">developer contest</a> at 10gen, I started work on a <a href="http://twitter.com/#!/mongopress/status/106910297964560384/photo/1/large">new administration interface</a> for MongoPress whilst <a href="http://labs.laulima.com/members/ali/">Ali</a> set himself on the task of re-writing the installation process and better organising the general flow of perma-trail interactions with super-charged private nonces and cookie key protection of sensitive data. As a result, we&#8217;ve hit all new levels of stability and security. We&#8217;ve got a fresh look and feel that utilises HTML5 in new and interesting ways with drag and drop batch image uploading and AJAX powered page transitions with push states and history. Our installation process is as simple as it gets &#8211; boasting an all new &#8220;<strong>One Step Process</strong>&#8221; with inline importing of content. The default theme has been given a new object type called &#8220;<a href="http://mongopress.org/mongopress-hq">places</a>&#8220;, which have been used for us to test the new <a href="http://mongopress.org/geo-feed">geoRSS</a> mu-plugin presently added to core, whilst also allowing us to showcase the new gMap shortcode functionality for displaying places on a map. With all this and <a href="http://trac.mongopress.org/trac/query?status=closed&amp;milestone=0.2">countless</a> other changes and bug-fixes, we&#8217;re proud to announce our first major milestone since launch. Our first &#8220;production ready&#8221; release. Our baby; <a href="http://mongopress.org">MongoPress 0.2</a></p>
<p>For those still unfortunate enough to not have an environment to install MongoDB and check-out MongoPress, we wanted to show you a couple of teasers from the administrative pages, where the first image shows the dashboard and the second shows drag and drop batch image uploading.</p>
<p><a href="http://mongopress.org/teasers/mongopress-admin-teaser-v02-dashboard.jpg"><img src="http://mongopress.org/teasers/mongopress-admin-teaser-v02-dashboard.jpg"></a><br />
<a href="http://mongopress.org/teasers/mongopress-admin-teaser-v02-media.jpg"><img src="http://mongopress.org/teasers/mongopress-admin-teaser-v02-media.jpg"></a></p>
<p>In addition to this, there are now several websites out there also using MongoPress.</p>
<ul>
<li><a href="http://smalley.my">http://smalley.my/</a></li>
<li><a href="http://www.libertyresourcing.co.uk/">http://www.libertyresourcing.co.uk/</a></li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://labs.laulima.com/mongodb-cms-mongopress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What&#8217;s new in MongoPress 0.1.2 &#8211; The MongoDB, PHP NoSQL CMS</title>
		<link>http://labs.laulima.com/mp012-mongodb-cms-php-nosql/</link>
		<comments>http://labs.laulima.com/mp012-mongodb-cms-php-nosql/#comments</comments>
		<pubDate>Wed, 03 Aug 2011 12:03:35 +0000</pubDate>
		<dc:creator>Mark Smalley</dc:creator>
				<category><![CDATA[MongoPress]]></category>

		<guid isPermaLink="false">http://labs.laulima.com/?p=153</guid>
		<description><![CDATA[It&#8217;s been just over two weeks since we first launched MongoPress 0.1 &#8211; since then; we&#8217;ve had over 1,000 downloads, which considering the niche server requirements needed to run MongoPress; is impressive. In the city of Shenzhen, we&#8217;ve even been ranked in the top 20,000 most visited websites! Since the initial buzz of the release [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align:justify">
<p>It&#8217;s been just over two weeks since we first launched <a href="http://mongopress.org">MongoPress</a> 0.1 &#8211; since then; we&#8217;ve had over 1,000 downloads, which considering the niche server requirements needed to run MongoPress; is impressive. In the city of Shenzhen, we&#8217;ve even been <a href="http://www.alexa.com/siteinfo/mongopress.org">ranked</a> in the top 20,000 most visited websites!</p>
<p>Since the initial buzz of the release v0.1 we&#8217;ve concentrated on making MongoPress even more stable and easier to install. Valuable feedback from <a href="http://twitter.com/mitchitized">Mitch</a>, means that all PHP notice and warning messages have been fixed. v0.1.2 is a big step up from our first release, we have successful installs on Windows 7 with XAMP, Debian Squeeze with Apache and Nginx.</p>
<p>Some highlights from the 40+ tickets we closed during the 0.1.1 and 0.1.2 development cycles includes:</p>
<ul>
<li>Improved Plugin Functionality &#8211; but even still, this is our weakest area and will be vastly improved upon by 0.2</li>
<li>Improved Site Options &#8211; can now change the site name, description and cookie expiration rate from the administrative pages</li>
<li>Improved Core Mu-Plugins &#8211; download counter improvements and NEW contact form plugin added &#8211; these will be removed from core by 0.2</li>
<li>Working Enque Methods for Theme and Admin pages (in headers and footers)</li>
<li>Attribute Filters for all &#8220;a&#8221; and &#8220;img&#8221; tags &#8211; useful for SEO, etc</li>
<li>Fully Working Administrative Themes (see themes/default/admin/_README.txt)</li>
<li>Geo-Location Functionality at Core (add lng lat via custom fields then query objects based on location)</li>
<li>Short-Code Functionality for Adding Images and Downloads from GridFS</li>
<li>Pretty Media Slugs (such as http://yourdomain/media/image.jpg linked to GridFS)</li>
<li>Improved HTML5 Structure</li>
<li>Improved Language Detection</li>
<li>Improved Stability &#8211; now developed in an ERROR_ALL environment</li>
</ul>
<p>MongoPress needs your help. We need people from all around the world to know that there is a NoSQL CMS that is powered by three of the most stable frameworks available in their fields. MongoDB, PHP and jQuery &#8211; by using this as our base, and derivations of several WordPress APIs &#8211; we have a platform that will be easy for developers to understand and manipulate, where we are allowing all facets of the installation to be customised and themed, from the administrative pages, structure and content; everything can be themed, translated and customised through hooks and filters and vast selection of unique functions only available with MongoDB; such as instant replication, load-balancing, distributed media storage and serving capabilities; right through to fully integrated geo-location formatting and querying. We have a LONG way left to go, especially in refining our administrative UX, but since this can already be fully themed, we employ you to do a better job for us! In the meantime, we want to continue focusing on unique features, and have a whole host left up our sleeves&#8230;</p>
<p>Let us know about your successful installations &#8211; on Mac OS, on WinXP on Android phones &#8211; we&#8217;re excited to know where MongoPress is being used or tested.</p>
<p>Thanks again for all of your support thus far!</p>
<ul>
<li><a href="http://mongopress.org">Download MongoPress</a></li>
<li><a href="http://twitter.com/mongopress">Follow MongoPress on Twitter</a></li>
<li><a href="http://www.facebook.com/pages/MongoPress/177184802345638">Like MongoPress on Facebook</a></li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://labs.laulima.com/mp012-mongodb-cms-php-nosql/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Introducing MongoPress &#8211; MongoDB CMS &#8211; an OpenSource High-Performance Platform</title>
		<link>http://labs.laulima.com/introducing-mongopress-mongodb-cms-an-opensource-high-performance-platform/</link>
		<comments>http://labs.laulima.com/introducing-mongopress-mongodb-cms-an-opensource-high-performance-platform/#comments</comments>
		<pubDate>Sat, 09 Jul 2011 02:03:36 +0000</pubDate>
		<dc:creator>Mark Smalley</dc:creator>
				<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[MongoPress]]></category>

		<guid isPermaLink="false">http://labs.laulima.com/?p=116</guid>
		<description><![CDATA[q]]></description>
			<content:encoded><![CDATA[<p>It all started with a <a href="http://labs.laulima.com/how-to-import-7-million-locations-from-geonames-to-mysql-then-into-mongodb-so-they-be-compared-and-optimized-for-location-queries/">challenge</a>. I was asked how quickly I could scan through 7 million or more locations and find the ten closest locations ordered by distance. To be clear, we have spent a lot of time perfecting our MySQL queries for locations, and the quickest we could perform such a query on a data-set as large as 7 million plus records (without caching) was 165 seconds. Obviously, this was not good enough, so I started investigating NoSQL, where MongoDB quickly became my preferred choice, specifically due to its geo-location features and the fact that it was now powering Foursquare.</p>
<p>Sure enough; with MongoDB, we were able to perform the exact same query with the exact same data in only 0.02 seconds &#8211; <strong>over 8,000 times faster</strong> than MySQL, so with a love for WordPress and an instant obsession with MongoDB, I was quick to register the <a href="http://mongopress.com">mongopress</a> domain. What I assumed would be a relatively easy task to build a plugin that could connect WordPress and MongoDB, quickly grew into something of epic proportions, and after digging deeper into both WordPress and MongoDB, I realized that WordPress had been built from the ground-up with SQL and a grand table-schema in mind. It did not take long for the penny to drop, and my mind started working over-time on the possibilities of a CMS that was built from the ground-up to best utilise MongoDB.</p>
<p>With that in mind, we would like to introduce you to <a href="http://mongopress.org">MongoPress</a>; where we have taken some of the best features from WordPress, and combined them into our our own lightweight MongoDB-based framework. With an emphasis on security, speed and limitless flexibility; MongoPress has the essential features needed for managing content on the web. We have tried to make as few assumptions as possible, allowing for a truly customised experience. We have tried and will continue trying to only include the absolute essentials in core, and if it could be added as a plugin, it will &#8211; from RSS and Comments to more traditional analytics and sitemaps; these will all be optional plugins. Instead, we will be concentrating on core MongoDB capabilities, such as out-of-the-box scaling through support for replica-sets and sharding, as well as geo-location features and GridFS support for media.</p>
<h4>What is MongoPress presently NOT&#8230;?</h4>
<p>MongoPress is <strong>NOT</strong> recommended for production use and has only be released early as a technology preview.</p>
<p>MongoPress is <strong>NOT</strong> a fully-loaded all-frills CMS and is lacking a lot of features people have come to expect from WordPress, but as a result, it is also much more flexible and can be easily customised with design, content and administrative templates.</p>
<h4>So what can we do with MongoPress 0.1 &#8230;?</h4>
<p>MongoPress 0.1 includes the following working features:</p>
<ul>
<li>Lightening Fast Reflexes</li>
<li>Local / Remote MongoDB Support with Replica-Sets and Sharding</li>
<li>Really Simple Installation Wizards / Process</li>
<li>Powerful Perma-Trail Functionality</li>
<li>WordPress Plugin API (hooks and filters)</li>
<li>WordPress Translation Functionality</li>
<li>Non-GUI-Based Theme Management</li>
<li>Administrative Access to MongoDB Objects</li>
<li>Additional Publication View Mode for Editing Objects</li>
<li>SHA(256) SALTED Security and Authentication</li>
<li>HTML Importation / Content Template Functionality</li>
<li>GridFS Media Support for Images and ZIPs (tracking downloads and views)</li>
</ul>
<h4>What did not make it into the initial release&#8230;?</h4>
<p>The following items did not make it into our 0.1 initial release but are presently scheduled for 0.2:</p>
<ul>
<li>Core GUI for Theme / Plugin Management</li>
<li>Ability to Develop Themes in HTML</li>
<li>Core Geo-Location Support</li>
<li>HTML5 Audio / Video Support for Default Theme</li>
</ul>
<h4>What plugins have we already built&#8230;?</h4>
<p>The following list are included mu-plugins that are in extremely crude states, but demonstrate existing flexibility that allows the bravest of souls to run in a production environment, as we are for <a href="http://mongopress.org">MongoPress</a> itself:</p>
<ul>
<li>Download Counter (with GridFS support)</li>
<li>Default Header (with GridFS support)</li>
<li>Analytics Plugin (for Google Analytics)</li>
</ul>
<h4>What plugins are at the top of our list&#8230;?</h4>
<p>The following list are plugins we plan to develop if not already in development when required:</p>
<ul>
<li>Contact Form Plugin</li>
<li>Comment Plugin</li>
<li>RSS Plugin</li>
<li>Sitemap Plugin</li>
</ul>
<h4>How can you help&#8230;?</h4>
<p>If you think that we might be on to something and want to help-out, please get in touch. If you simply want to show support, let people know about us. Write a post or send a tweet, shout it from the roof-tops if you can. We need to hear from you guys. We need to know that this is something you want, and so the more we hear from you, the better our ability becomes in responding to your needs.</p>
<p>Follow us on Twitter &#8211; at <a href="http://twitter.com/mongopress">@mongopress</a></p>
<p>Download our nightly-build via SVN &#8211; at <a href="http://svn.mongopress.org/trunk/">http://svn.mongopress.org/trunk/</a></p>
<p>You can keep track of bugs and up-coming features via MongoTrac &#8211; at <a href="http://trac.mongopress.com">http://trac.mongopress.org</a></p>
]]></content:encoded>
			<wfw:commentRss>http://labs.laulima.com/introducing-mongopress-mongodb-cms-an-opensource-high-performance-platform/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To: Import 7 Million Locations from GeoNames to MySQL, then into MongoDB so they can be compared and optimized for Location Queries</title>
		<link>http://labs.laulima.com/how-to-import-7-million-locations-from-geonames-to-mysql-then-into-mongodb-so-they-be-compared-and-optimized-for-location-queries/</link>
		<comments>http://labs.laulima.com/how-to-import-7-million-locations-from-geonames-to-mysql-then-into-mongodb-so-they-be-compared-and-optimized-for-location-queries/#comments</comments>
		<pubDate>Mon, 16 May 2011 01:57:35 +0000</pubDate>
		<dc:creator>Mark Smalley</dc:creator>
				<category><![CDATA[Benchmarks]]></category>
		<category><![CDATA[Location Queries]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://labs.laulima.com/?p=60</guid>
		<description><![CDATA[It&#8217;s a long title I know, but it only comes half-close to the title I really wanted to use&#8230; So, like everyone else who&#8217;s been paying any kind of attention to recent database technology trends, I&#8217;d heard about this No-SQL stuff, heard it was fast, and far more approachable to your average developer due to [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s a long title I know, but it only comes half-close to the title I really wanted to use&#8230;
<p>So, like everyone else who&#8217;s been paying any kind of attention to recent database technology trends, I&#8217;d heard about this No-SQL stuff, heard it was fast, and far more approachable to your average developer due to the JSON based formatting, but had never had the time to sit down and really investigate things. And then I heard about MongoDB, specifically about their superb geo-location functions &#8211; <a href="http://www.mongodb.org/display/DOCS/Geospatial+Indexing" title="A good overview of MongoDB geo-location features">http://www.mongodb.org/display/DOCS/Geospatial+Indexing</a> &#8211; and as you may know already, I&#8217;m a bit of a geo-location nut-case, so was instantly hooked when I also heard that Foursquare was using MongoDB too.</p>
<p>So where to start&#8230;? We first needed some geo-data, and where better to get that than from <a href="http://download.geonames.org/export/dump/" title="download OpenSource geo-data from GeoNames">GeoNames</a> &#8211; where you can download the <a href="http://download.geonames.org/export/dump/allCountries.zip">allCountries.zip</a> file (containing 7 Million+ records at over 200 MB), or simply grab the country-specific information for the country you reside.</p>
<p>We will need to get the data into MySQL, not only so that we can compare the speeds for proximity searches, but also so that we can learn a valuable lesson on how to export from MySQL into MongoDB, which really is both flexible and easy.</p>
<p>If we plan to use the GeoNames data, we <strong>MUST</strong> first create a table using the following SQL (with the field names being specifically important for the next stage):</p>
<pre class="brush: sql; title: ;">
CREATE TABLE `geonames` (
    `geonameid` int(10) unsigned NOT NULL default '0',
    `name` varchar(200) NOT NULL default '',
    `ansiname` varchar(200) NOT NULL default '',
    `alternatenames` varchar(2000) NOT NULL default '',
    `latitude` double NOT NULL default '0',
    `longitude` double NOT NULL default '0',
    `feature_class` char(1) ,
    `feature_code` varchar(10) ,
    `country_code` char(2),
    `cc2` varchar(60),
    `admin1_code` varchar(20) default '',
    `admin2_code` varchar(80) default '',
    `admin3_code` varchar(20) default '',
    `admin4_code` varchar(20) default '',
    `population` bigint(11) default '0',
    `elevation` int(11) default '0',
    `gtopo30` int(11) default '0',
    `timezone` varchar(40),
    `modification_date` date default '0000-00-00',
    PRIMARY KEY (`geonameid`)
) CHARACTER SET utf8 ;
</pre>
<p></p>
<p>With the <strong>geonames</strong> table created, we can import the data contained within the TXT file we just downloaded from GeoNames by using SQL similar to the following (where you will need to replace the location of the TXT file to the location you just extracted it to from the ZIP file you downloaded):</p>
<pre class="brush: sql; title: ;">
LOAD DATA INFILE 'C:/xampp/htdocs/allCountries.txt' INTO TABLE geonames(
    geonameid, name, ansiname, alternatenames, latitude, longitude, feature_class, feature_code, country_code, cc2, admin1_code, admin2_code, admin3_code, admin4_code, population, elevation, gtopo30, timezone, modification_date
)
</pre>
<p></p>
<p>We should now have over 7 million places in our database (assuming you were brave enough to use the allCountries.txt file, which to be honest, may be too big for the next stages and cause you several problems like it did when running it on my personal PC at home). Once you have the records in your MySQL database, do not forget to add an index to the &#8220;latitude&#8221; and &#8220;longitude&#8221; fields in order to give the tests a fair chance later.</p>
<p>At this stage, we should probably start thinking about getting MongoDB set-up, and fortunately, the online documentation and general community-spirit for MongoDB is a jolly-fine one at that. For the purpose of this comparison, we will be using MongoDB and PHP to test the results, but in a future &#8220;How To&#8221;, I also hope to document my findings for NodeJS too!</p>
<p>Let&#8217;s download MongoDB &#8211; <a href="http://www.mongodb.org/downloads" title="download MongoDB">http://www.mongodb.org/downloads</a> &#8211; then run-through the getting-started guides &#8211; <a href="http://www.mongodb.org/display/DOCS/Quickstart" title="getting started with MongoDB">http://www.mongodb.org/display/DOCS/Quickstart</a>. I found set-up on the PC and Mac equally as easy. Simply download the package, save somewhere sensible, create the necessary &#8220;data&#8221; folder, then run the two recommended console executables &#8220;mongod.exe&#8221; and &#8220;mongo.exe&#8221; and if 3+3 equals 6 everything&#8217;s working properly! For the benefit of getting to the meat and bones of this How To, I&#8217;m going to assume that setting-up MongoDB was a breeze and that you were then capable of also copying the correct .dll (for windows) or .so (for Mac) into the correct &#8220;extension&#8221; folder as specified by your php.ini file and documented here &#8211; <a href="http://www.mongodb.org/display/DOCS/PHP+Language+Center">PHP Drivers for Mongo</a>.</p>
<p>We are now ready to import the MySQL data into MongoDB, and although the method I am about to show you is not the preferred method for large data-sets (which should use the import function), showing you this way teaches you the most fundamental MongoDB functions, which includes adding new collections (tables) and objects (records), but also updating those objects and then retrieving the objects, all from PHP in syntax we as PHP developers should be very comfortable with. In fact, the following code provides everything you need in order to not only import the data from MySQL to MongoDB, but also to run comparative tests to see how fast each of the databases can run and return the same results.</p>
<p></p>
<blockquote><p><strong>Before you begin, please note that importing all 7 Million records using the methods below from MySQL to MongoDB is going to take some time, several hours, if not all day (and then some, especially using these methods), so if you are doing this as a way to get started and want some immediate feedback, you REALLY should consider importing one of the country specific .txt files from GeoNames, or using the country_code and (or) limit variables to migrate only a portion of the whole MySQL data into MongoDB.</strong></p></blockquote>
<p></p>
<p><strong>Either way, feel free to use, improve and comment on the following code as required</strong> (as a reminder, this is not the best way to import large data-sets to MongoDB but have done it this way so that it&#8217;s easy to understand the fundamentals):</p>
<pre class="brush: php; title: ;">
// We need this function for running stop-watch later...
function ms_microtime_float(){
    list($usec, $sec) = explode(&quot; &quot;, microtime());
    return ((float)$usec + (float)$sec);
}

// We need this function for making the most optimised MySQL proximity query available...
// Simply provide a database name, your current Lat / Lng and optional DB Limits and Maximum Distances...
function ms_get_locations_by_distance_using_sql($database_name='geonames',$lat,$lng,$limit=100,$distance=100,$country_specific=false){
    if($country_specific){ $extra_where_clause = &quot;AND country_code = 'MY'&quot;; }else{ $extra_where_clause=''; }
    if($limit&gt;0){ $limit = 'LIMIT 0, '.$limit; }else{ $limit=NULL; }
    $lng1 = $lng - $distance / abs(cos(deg2rad( $lat ) ) *69 );
    $lng2 = $lng + $distance / abs(cos(deg2rad( $lat ) ) *69 );
    $lat1 = $lat - ( $distance /69 );
    $lat2 = $lat + ( $distance /69 );
    /* THIS REALLY IS THE BEST WAY TO PERFORM PROXIMITY SEARCH IN MYSQL */
    $nearest_locations_ordered_by_distance = &quot;SELECT *,
        ( 6371 * acos( cos( radians( $lat ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians( $lng ) ) + sin( radians( $lat ) ) * sin( radians( latitude ) ) ) ) AS distance
        FROM $database_name
        WHERE longitude between $lng1 and $lng2
        AND latitude between $lat1 and $lat2
        $extra_where_clause
        HAVING distance &lt; $distance
        ORDER BY distance
        $limit&quot;;
    return $nearest_locations_ordered_by_distance;
}

/*
 *  THESE ARE OUR OPTIONS
 *
 *  In order to initially import data from MySQL to MongoDO use:
 *
 *  $collect_mongo_results = false;
 *  $loop_through_sql = true; // SET TO FALSE IF ONLY INTERESTED IN MONGO RESULTS
 *  $add_to_mongo = true;
 *  $print_arrays = false;
 *
 *  In order to compare times for collecting results in both MySQL and MongoDB use:
 *
 *  $collect_mongo_results = true;
 *  $loop_through_sql = true; // SET TO FALSE IF ONLY INTERESTED IN MONGO RESULTS
 *  $add_to_mongo = false;
 *  $print_arrays = true;
 *
*/
$collect_mongo_results = false;
$loop_through_sql = true;
$add_to_mongo = true;
$print_arrays = false; // Be careful, with 7 million results, this can take time
$limit = -1; // Set this to -1 if you wish to import everything from MySQL to MongoDB else add limit as number
$maximum_distance = 100; // This represents the maximum distance in KM for proximity search
$database_name = 'geonames'; // This will also be used for the MongoDB name
$table_name = 'countries'; // This will also be used as the MongoDB collection name
$mysql_host = 'localhost';
$mysql_username = 'root';
$mysql_password = '';
// These default Lat / Lng Coordinates are for Malaysia
$current_latitude = 3.190908; // Do not use a string!
$current_longitude = 101.682243; // Do not use a string!
// This country code is for Malaysia
// Change to false if wanting to run queries on all records...
$country_code = false; // This is used to perform sub-set queries on specific countries...
/* END OF OPTIONS */

// Connect to Mongo
$m = new Mongo();
// Select / Create a Database
$db = $m-&gt;$database_name;
// Select / Create a Collection (table)
$collection = $db-&gt;$table_name;

/* THIS ALLOWS SCRIPTS TO RUN WITHOUT TIMING OUT */
set_time_limit(0);

if($collect_mongo_results){

    /* START TIMING MONGO */
    $time_start = ms_microtime_float();

    // Start building MongoDB query
    /* PAY EXTRA ATTENTION TO ORDER OF LONGITUDE THEN LATITUDE */
    /* THIS IS VERY IMPORTANT FOR MONGODB - OTHERWISE RESULTS WILL BE WRONG !!! */
    $this_latlng = array('lng'=&gt;$current_longitude,'lat'=&gt;$current_latitude);

    $mongo_near_query = array('geoNear'=&gt;$table_name,'near'=&gt;$this_latlng,'$spherical'=&gt;true,'$maxDistance'=&gt;$maximum_distance/6378,'num'=&gt;$limit);
    $cursor = $db-&gt;command($mongo_near_query);

    /* THE SAME QUERY CAN BE RUN IN MONGO CONSOLE USING THE FOLLOWING */
    //-&gt; db.runCommand({geoNear:&quot;countries&quot;,near:[101,3],spherical:true,maxDistance:100/6378,num:10})

    if($print_arrays){
        // iterate through the results
        foreach ($cursor['results'] as $obj) {
            echo '&lt;br /&gt;This is MongoDB Array:&lt;br /&gt;';
            echo '&lt;pre&gt;';
            print_r($obj);
            echo '&lt;/pre&gt;';
        }
    }
    /* END MONGO TIMER AND DISPLAY RESULTS */
    $time_end = ms_microtime_float();
    $time = $time_end - $time_start;
    $mongo_results = &quot;&lt;br /&gt;Collected and Printed using MongoDB in $time seconds&lt;br /&gt;&quot;;
    echo $mongo_results;

}

if($loop_through_sql){

    /* START SQL TIMER */
    $time_start = ms_microtime_float();

    // Connect to MySQL
    $link = mysql_connect($mysql_host, $mysql_username, $mysql_password);
    if (!$link) {
        die('Could not connect: ' . mysql_error());
    }

    // Connect to
    if (!mysql_select_db($database_name)) {
        die('Could not select database: ' . mysql_error());
    }

    /* WHICH QUERY TO RUN...? DEPENDS ON OPTIONS ABOVE */
    if($add_to_mongo){
        if($country_code){ $where_clause = &quot;WHERE country_code = 'MY'&quot;; }
        $query = 'SELECT * FROM '.$table_name.$where_clause;
    }else{
        $query = ms_get_locations_by_distance_using_sql($table_name,$current_latitude,$current_longitude,$limit,$maximum_distance,$country_code);
    }

    // Perform Query
    $result = mysql_query($query);

    // Check result
    // This shows the actual query sent to MySQL, and the error. Useful for debugging.
    if (!$result) {
        $message  = 'Invalid query: ' . mysql_error() . &quot;\n&quot;;
        $message .= 'Whole query: ' . $query;
        die($message);
    }

    // Use result
    // Attempting to print $result won't allow access to information in the resource
    // One of the mysql result functions must be used
    // See also mysql_result(), mysql_fetch_array(), mysql_fetch_row(), etc.
    while ($row = mysql_fetch_assoc($result)) {
        if($print_arrays){
            echo '&lt;br /&gt;This is MySQL Array:&lt;br /&gt;';
            echo '&lt;pre&gt;';
            print_r($row);
            echo '&lt;/pre&gt;';
        }
        /* END SQL TIMER */
        $time_end = ms_microtime_float();
        $time = $time_end - $time_start;

        /* NOW NEED TO ADD DATA TO MONGO TOO */
        if($add_to_mongo){
            $obj = array();
            foreach($row as $key =&gt; $value){
                $obj[$key] = $value;
            }
            // This is the MongoDB PHP Function for inserting objects (records)
            $collection-&gt;insert($obj);
        }
        // In order to use MongoDB Geo-Spatial Indexing we need a Lng / Lat field
        // This shows us how to use the MongoDB PHP Update function
        $collection-&gt;update(array(&quot;geonameid&quot; =&gt; $row['geonameid']), array('$set' =&gt; array(&quot;latlng&quot; =&gt; array('lng'=&gt;(float)$row['longitude'],'lat'=&gt;(float)$row['latitude']))));
        // Create Geo-Spaital Index In Mongo Console (once this field has been added) using:
        // db.countries.ensureIndex({latlng:'2d'})
    }

    /* THEN PRINT RESULTS */
    echo &quot;&lt;br /&gt;Collected and Printed using MySQL in $time seconds&lt;br /&gt;&quot;;
    if($collect_mongo_results){
        echo &quot;WHERE AS &quot;.$mongo_results;
    }

    // Free the resources associated with the result set
    // This is done automatically at the end of the script
    mysql_free_result($result);
    mysql_close($link);

}
</pre>
<p></p>
<p>Several things to remember before running or after checking the results of the comparisons is whether you remembered to added the MySQL indexes to your latitude and longitudes, not to mention whether you added the geo-spatial index to your MongoDB, to do which, you will need to use the following command from within the Mongo Console (geeky I know &#8211; there are some GUIs, but this is much easier than it looks):</p>
<pre class="brush: jscript; title: ;">
db.countries.ensureIndex({latlng:'2d'})
</pre>
<p></p>
<p>Some other simple yet useful commands for the console include dropping databases:</p>
<pre class="brush: jscript; title: ;">
db.geonames.drop()
</pre>
<p></p>
<p>By default, opening the Mongo Console launches the &#8220;test&#8221; database, so to switch from that to <strong>geonames</strong> is as simple as typing:</p>
<pre class="brush: jscript; title: ;">
use geonames
</pre>
<p></p>
<p>In conclusion, <strong>MongoDB is FAST</strong>. In searching through 65,411 records / objects (as I myself only imported the places for Malaysia in order to save time and get to the learning part), and displaying only those within a 100 KM radius, and then having those results limited to 10, ordered by distance with the closest first, and echoed out onto the page took <strong>0.23555 seconds for MySQL</strong>, where as that very same query providing the very same results took only <strong>0.00152 seconds with MongoDB</strong> &#8211; and on several occasions, it even came in around the <strong>0.00095</strong> mark! And to think that that&#8217;s with just one user accessing the query. The biggest problem with MySQL and the reason I initially sought alternatives was the fact that only one person can access the database at one time, where concurrent queries get added to a queue and need to wait their turn. With MongoDB, this is not the case, so really, truth be known, there is no comparison between them! But we will be running some concurrent tests soon, as well as running the same queries using the complete 7 Million record set&#8230;</p>
<h3>But how do we import all 7 Million+ records and perform tests on those&#8230;?</h3>
<p>By <strong>NOT</strong> using the methods above! I tried several times and several different ways to import all 7 million records, and the quickest most reliable method I could find was to first export the MySQL as CSV. I tried several times to use a mysqldump from console, but could never get the formatting right. Believe it or not, the most Mongo-Friendly method was to export from phpMyAdmin in CSV for MS Excel format (with the first row being field names) as this was able to then utilize the mongoimport function. However, whenever I tried to export the entire set, I ran into problems. What I ended-up doing was exporting a million records at a time as CSV.</p>
<p>Once you have all 8 CSV files, you can then import them into MongoDB using the following console commands:</p>
<pre class="brush: jscript; title: ;">
mongoimport --db geonames --collection countries --type csv --file geonames_part1.csv --headerline --upsert
</pre>
<p></p>
<p>Do this for each part, and remember this must be done from a standard terminal console, not from the MongoDB console, which was my first mistake! After we have all 7 Million plus records into the database, we are going to need to add in the latlng / loc field, which does not yet exist and is needed by MongoDB for the geo-spatial indexing. To do this, the quickest method I found was to use a JS query. To do that, you will first need to create a new JavaScript with contents such as:</p>
<pre class="brush: jscript; title: ;">
db.countries.find().forEach(function(data) {
    db.countries.update({_id:data._id},{$set:{loc:{lng:parseFloat(data.longitude),lat:parseFloat(data.latitude)}}});
})
</pre>
<p></p>
<p>We then need to query the MongoDB using that JS file, which is perhaps <strong>my most favourite MongoDB feature</strong> and can be performed from a regular terminal (not the MongoDB console) using syntax such as:</p>
<pre class="brush: jscript; title: ;">
mongo geonames add_latlng.js
</pre>
<p></p>
<p>Once we have that in place, we can add the Geo-Spatial Index (from the Mongo Console) by typing:</p>
<pre class="brush: jscript; title: ;">
db.countries.ensureIndex({loc:&quot;2d&quot;})
</pre>
<p></p>
<p><strong>The results are phenomenal:</strong></p>
<p>Querying 7.8 Million records using MySQL and finding the 10 nearest locations ordered by distance took an average of 165 seconds!</p>
<p><strong>With MongoDB, that same query took only 0.02 seconds!</strong></p>
<p>Other than that, what&#8217;s next&#8230;?</p>
<p><strong><a href="http://mongopress.org">MongoPress</a></strong> &#8211; for it is this that started the future of NoSQL CMS : -)</p>
<p>You may also be interested in <a href="http://labs.laulima.com/mongodb-vs-mysql-performance-benchmarks-cms/">MongoDB Vs MySQL – Benchmarks Re-Creating Typical CMS Functionality to Compare Performance of MySQL and MongoDB in PHP / Apache</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://labs.laulima.com/how-to-import-7-million-locations-from-geonames-to-mysql-then-into-mongodb-so-they-be-compared-and-optimized-for-location-queries/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Welcome</title>
		<link>http://labs.laulima.com/welcome/</link>
		<comments>http://labs.laulima.com/welcome/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 04:14:35 +0000</pubDate>
		<dc:creator>LauTeam</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://labs.laulima.com/?p=1</guid>
		<description><![CDATA[Welcome to Laulima Labs, built for those working with Laulima to keep track of geo-social news and document the tools we work with and develop&#8230;]]></description>
			<content:encoded><![CDATA[<p>Welcome to Laulima Labs, built for those working with Laulima to keep track of geo-social news and document the tools we work with and develop&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://labs.laulima.com/welcome/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

