Building a Location-based Platform with MongoDB from Zero
1. MongoDB Bangalore Conference
Oct 26th 2012
Building a Location-based platform
with MongoDB from Zero
Raviteja Dodda
Co-Founder & CTO, Pipal Tech Ventures
2. DelightCircle
• Offers, New Arrivals & Rewards
from 250 + brands and 12,000 +
stores across the country.
• Discover what’s nearby, Engage
with your favorite brands, and Earn
real rewards.
SMS: ‘@delight’ to 92431-92431
Website: DelightCircle.com
3. Some highlights
“DelightCircle is an app to help you pick out the best deals in the shops around
you, and also hand you points for just walking into them. A must-have for all
ye Android and iOS shopaholics.”
ThinkDigit, Sep 2012
“DelightCircle is featured as one of the top 6 mobile apps across the country.”
NASSCOM Emerge AppFame Aug 2012
“DelightCircle is featured by Samsung App Store & Blackberry App World.”
Sep, Oct 2012 - present
4. MongoDB & MongoEngine power the
data storage & processing parts of
DelightCircle backend platform
6. Some Examples
• The data can be of users.
User = {‘loc’:[12.97,72.023], ‘name’:’xyz’, ‘email’:’..’, ..}
• The data can be of local businesses.
Place = {‘loc’:[12.97,72.023], ‘name’:’mnz’, ‘categories’:’..’, ..}
• The data can be of Photos.
Photo = {‘loc’:[12.97,72.023], ‘file’: File(), ‘taken_by’:’User()’, ..}
• and can be many more types,
leading to the next generation of location-based applications.
7. Let’s Dive in !
Build the backend for a check-in based rewards app
8. Requirements
• Users can check-in to places using the app, and earn
rewards based on check-ins.
Ex: GET 10% OFF on every 2nd check-in.
• Rewards can be created by the merchant, and can be assigned
to specific places of his business.
• Rewards should be searchable by users based on the
location and some keywords.
9. Why MongoDB ?
• Fast, Easy and Schema-less.
• Multiple Language Support & Faster development cycle.
• Document Object store – maps much more cleanly to OOP.
• Replica sets/Automatic failover of failed nodes.
• Support for Geo-spatial Indexes and Queries.
It cheats to make the math easier/faster by assuming a flat earth
(where 1 degree of latitude or longitude is always the same).
Has methods to handle curvature of Earth (Spherical – if needed)
10. MongoDB – a database with real
world solutions for real world
problems
Simple to use & flexible.
11. MongoEngine
Python MongoDB
MongoEngine
• Document Object Mapper for Python and MongoDB
•Built on top of PyMongo &Very similar to popular Django
ORM
• Add all your validation stuff in MongoEngine.
$easy_install mongoengine
12. Structuring & indexing your data
depends on the way you want to
query your data
Data modeling differs between use-
cases.
13. Place Reward
Id
Id
[Place-ref] title
name
[{Place-ref,
location (2d- 1 to n
Loc}, {Place-ref,
index)
Loc}, ….. ]
tags, etc.
tags, etc.
Place-ref
1 to 1 Check-in
User
Id
Id User-ref
name User-ref Place-ref
email (index) time (index)
mobile 1 to 1 action
Gender
age, etc.
Schema Design
14. Let’s start with Places
Place = {
_id: ObjectId(),
loc: [12.97,72.23], //suggested option
name: ‘A’,
tags: [‘food’, ‘restaurant’]
}
Place= {
_id: ObjectId(),
loc: {x:12.97, y:72.23},
name: ‘A’,
tags: [‘electronics’, ‘mobiles’]
}
loc: {lon: 40.739, lat:73.992}, ensure that you follow
the same order for consistency.
15. Place Model - MongoEngine
import mongoengine
connect(‘my_database’) // connecting to DB
Class Place(Document):
loc= GeoPointField() // Geo2D index is
automatically created
name = StringField(max_length=50)
tags = ListField(StringField(max_length=300))
P = Place(name=‘Pizza Hut’, loc=[12.97,77.9],
tags=[‘pizza’, ‘restaurant’, ..])
p.save() // saves the document to Mongo
16. Some Geospatial Queries
Find the closest 20 places to a given location.
JavaScript Shell
> db.places.find({‘loc’: {‘$near’: [12.62, 72.323]}}).limit(20)
Python (MongoEngine)
Place.objects(loc__near = [12.62, 72.323]).limit(20)
Results are sorted by distance, no need of an additional
sort.
17. Bounds Queries
Find the closest 20 places to a given location that are
within a distance of 5 km.
JavaScript Shell
> db.places.find( { loc : { $near : [12.62,72.323] ,
$maxDistance : 5/earth_radius } } ).limit(20)
Python (MongoEngine)
Place.objects(loc__within__distance =[ [12.62, 72.323],
5/earth_radius]).limit(20)
Results are not sorted by distance, hence faster
18. User & Check-ins data model
User = {
_id: ObjectId(),
name: ‘A’,
email: ‘xyz@domain.com’, etc.
}
Check-in = {
_id: ObjectId(),
place: { "$ref" : "Places", "$id" : ObjectId()},
user: { "$ref" : ”Users", "$id" : ObjectId()},
time: ISODate(),
etc.
}
19. Check-ins - MongoEngine
Class Check-in(Document):
user = ReferenceField(‘Users’, required=True),
place = ReferenceField(‘Places’, required=True),
time = DateTimeField(required = True)
meta = {
‘ordering’: [‘-time’],
‘indexes’: [(‘user’, ‘place’)]
}
A Compound Index is created on user and place, since
most of our queries will contain both.
20. Rewards data model
Reward = {
_id: ObjectId(),
name: ‘GET 10% OFF .. ‘,
places: [{ "$ref" : "Places", "$id" : ObjectId()}, { "$ref"
: “Places", "$id" : ObjectId()}, .. ]
etc.
}
If you want to query the rewards based on location
Reward = {
_id: ObjectId(),
places: [ { place: { "$ref" : "Places", "$id" :
ObjectId()}, loc: {x:0, y:0}} , .. ]
etc.
}
21. Rewards - MongoEngine
Class Reward(Document):
name = StringField(required=True),
places =
ListField(EmbeddedDocumentField(PlaceLocation)
)
tags = ListField(StringField())
num_checkins_required = IntField(default=1)
Class PlaceLocation(EmbeddedDocument):
place = ReferenceField(‘Places’)
loc = GeoPointField()
22. Find the rewards nearalocation which have tags –
‘food’ and ‘pizza’.
JavaScript Shell
db.Rewards.find({‘places.loc’:{‘near’:[12.62, 72.3]}, ‘tags’:
{‘$all’: [‘food’, ‘pizza’]}}).limit(20);
Python (MongoEngine)
Reward.objects(places__loc__near =[12.62,72.323],
tags__all = [‘food’, ‘pizza’]).limit(20)
You need to have a compound geo-spatial index defined on
both keys together for better performance of the query.
23. Conclusion
1. Spatial is easy and fun on MongoDB !!
2. You can now build your own check-in application (or)
also build your own field data entry system.
3. Running MongoDB on any cloud infrastructure is quite
easy.
PS: WE ARE HIRING – looking for smart hackers
Roles: Backend, iOS Developer, UI/UX Designer, etc.
Mail me at (or) come talk to
me.
24. Questions?
Thank You
Stay Hungry, Stay Foolish !!!
- Steve Jobs
raviteja@delightcircle.com
Twitter, Facebook - @raviteja2007
www.DelightCircle.com
Hinweis der Redaktion
Implications and Philoshophy of Client-side rendering
Why am I talking about location-based platforms ? Because we built one – DelightCircleGet some white color images for Android, iphone, bb, website, and SMSFor businesses, we provide a location-based marketing platform with a powerful CRM backend, and access to Analytics.
Let’s start with the location data.
Who are the python developers here ? Can I have a raise of hands ?MongoEngine provides the ability to define your documents well, and will validate the document while saving, as mongodb is schema-less.
You can embed the document some times, sometimes you need to refer. It all depends on the use-cases. Don’t worry about the normalization pieces in Mongo.
Define the Schema for Users, Rewards as well.
Document is a class of MongoEngine library, and our Place class inherits the Document class. This is the definition of our document.
Place.objects(loc__within_distance = [[12.62, 72.323], 1]).limit(20)Place.objects(loc__near = [12.62, 72.323]).limit(20)Find the closest 20 places to a given location that are within 1 degree of the location.Place.objects(name= ‘Pizza Hut’, loc__near = [12.62, 72.323]).limit(20)Find the closest 20 pizza hut’s near to a given location.
Place.objects(loc__within_distance = [[12.62, 72.323], 1]).limit(20)Place.objects(loc__near = [12.62, 72.323]).limit(20)Find the closest 20 places to a given location that are within 1 degree of the location.Place.objects(name= ‘Pizza Hut’, loc__near = [12.62, 72.323]).limit(20)Find the closest 20 pizza hut’s near to a given location.