I building a very simple price tracker web app. I am using MongoDB with pymongo. The user will enter the URL of the product he wishes to track and the desired amount, when the price goes below this amount, he should get an alert. It doesn't matter how many products he is tracking, I will send the alert when price changes in one product. I will sending generalized alert like 'Some of the product/s available at cheaper price' or something like that.
There are three collections in the database, one to store product details, one for user details and one to map products to the users who are tracking it.
A typical document in products
collection will be:
{
_id: ObjectId("53a2bfcfa7603606c2765342"),
name: "Nexus 7 from Google (7-Inch, 16 GB, Black)",
url: "http://rads.stackoverflow.com/amzn/click/B00DVFLJDS",
base_price: 222,
current_price: 213.96,
img_url: "http://i.imgur.com/something.jpg",
history: [
[
ISODate("2014-06-19T12:08:13.354Z"),
293
],
[
ISODate("2014-06-24T14:31:38.216Z"),
424
],
[
ISODate("2014-06-24T14:32:06.992Z"),
424
]
]
}
in users
, the tracked_products
contain the Object Id of the product document and the desired price:
{
_id: ObjectId("539c4adea760360886d7ef02"),
email_id: "[email protected]",
channels: {
'twitter': 'usertwitterid',
'ios_push_id': '45462722672762576422'
'android_push_id': '2572652754762474'
'chrome_push_id': '456456454646464'
},
tracked_products: [
[
ObjectId("53a2bfcfa7603606c2765342"),
200
],
[
ObjectId("53a2d2ada7603606c2765344"),
345
],
[
ObjectId("53a2d294a7603606c2765343"),
120
]
]
}
and lastly trackers
, here subscribers
contain the Object Id of user document who are tracking this product:
{
_id: ObjectId("77a2bfcfa7603606c2765399"),
product_id: ObjectId("53a2bfcfa7603606c2765342"),
subscribers: [
[
ObjectId("539c4adea760360886d7ef02"),
200
],
[
ObjectId("12a2bfcfa7603606c2765399"),
234
],
[
ObjectId("14a2bfcfa7603606c2765399"),
345
],
}
Following is the code, which checks for the current_price
and alerts the user if there is change in the price:
subscribers = set()
for product in product.collection:
# price changed? if yes, then update
current_price = get_current_price(product['url'])
if current_price == product['current_price']:
# no price change. move on
continue
product['history'].append((datetime.datetime.utcnow(), current_price))
# find the subscribers:
tracker_document = db.trackers.find_one({'product_id': product['_id']})
for tracker in tracker_document['subscribers']:
user_id, desired_price = tracker
if current_price <= desired_price:
subscribers.add(user_id)
product.collection.save(product)
if not subscribers:
# no price changes in any products!
sys.exit()
email_queue = list()
twitter_queue = list()
ios_push_queue = list()
droid_push_queue = list()
chrome_push_queue = list()
for user_id in subscribers:
user_document = db.users.find_one({'_id': user_id})
email_queue.append(user_document['email_id'])
twitter_queue.append(user_document['channels']['twitter'])
ios_push_queue.append(user_document['channels']['ios_push_id'])
droid_push_queue.append(user_document['channels']['droid_push_id'])
chrome_push_queue.append(user_document['channels']['chrome_push_id'])
alert_users(email_queue, twitter_queue, ios_push_queue, droid_push_queue, chrome_push_queue)
I am looking for any suggestions, code improvements/readability, performance improvement, schema change etc. Anything!
PS: I am aware this would be lot easier with RDBMS and join operations, but I am sticking with MongoDB as of now.