I’ve been reading the mongodocs and reading the tutorial.
For testing purposes, I have made this little script with python / pymongo.
Basically, 3 dbs, with 2 collections each, “orders” and “products”
The same products are inserted in the products collection, and one order is placed in each order collection, the difference is
the way products are “related” to orders, in one are linked, in other are embedded and the last are referenced.
Finally, updates one value in the product and prints it.
My questions are:
1 – Are the “relations” well done. reformulate: Is this the way a reference/embed/link is done?
2- Should the “embedded” order reflect the changes in item prices, reflect the change in the product, or it must be done by the script?
# -*- coding: utf-8 *-*
from pymongo import *
from bson import *
import sys
def connect():
try:
auxcon = Connection('localhost', 27017)
print "Connection: %s database_names: %s" % (
auxcon, auxcon.database_names())
return auxcon
except error.ConnectionFailure as cf:
print "Conection error: %s" % cf
sys.exit(0)
def newDB(db_name, conx):
try:
ldb = database.Database(conx, db_name + "_linked")
edb = database.Database(conx, db_name + "_embedded")
rdb = database.Database(conx, db_name + "_referenced")
return ldb, edb, rdb
except (error.TypeError, error.InvalidName) as err:
print "Error: %s" % err
sys.exit(0)
def newCollections(db_name):
try:
colprod = db_name.create_collection("products")
colord = db_name.create_collection("orders")
return colprod, colord
except errors.CollectionInvalid as err:
print "Collection alrready exists %s" % err
return db_name["products"], db_name["orders"]
def insertProducts(colname):
product = {"name": "Tablet", "price": 200, "desc": "Android tablet"}
product2 = {"name": "Phone", "price": 100, "desc": "Samsung Phone"}
try:
p1 = colname.insert(product, safe=True)
p2 = colname.insert(product2, safe=True)
return p1, p2
except errors.OperationFailure as err:
print "Error inserting %s" % err
return None, None
def updateProducts(colname):
for product in colname.find({}):
product["price"] = product["price"] * 110 / 100
colname.save(product)
def printProducts(colname):
print "DATABASE: %s COLLECTION: %s" % (
colname.database.name, colname.name)
for product in colname.find({}):
print product
def findOrders(colname):
print "DATABASE: %s COLLECTION: %s" % (
colname.database.name, colname.name)
for order in colname.find({}):
for key, value in order.items():
print "%s : %s" % (key, value)
if __name__ == "__main__":
cx = connect()
try:
cx.drop_database("carritodb_linked")
cx.drop_database("carritodb_embedded")
cx.drop_database("carritodb_referenced")
except errors.TypeError as err:
print "Error %s" % err
dbl, dbe, dbr = newDB("carritodb", cx)
licoll = newCollections(dbl)
emcoll = newCollections(dbe)
recoll = newCollections(dbr)
lp1, lp2 = insertProducts(licoll[0])
ep1, ep2 = insertProducts(emcoll[0])
rp1, rp2 = insertProducts(recoll[0])
linkedOrder = {"userInfo": "Alex Martinavarro", "items_chart": [lp1, lp2]}
linkedOrder = licoll[1].insert(linkedOrder, safe=True)
embeddedOrder = {"userInfo": "Alex Martinavarro", "items_chart": []}
embeddedOrder = emcoll[1].insert(embeddedOrder, safe=True)
embeddedOrder = emcoll[1].find_one(embeddedOrder)
for product in emcoll[0].find({}):
embeddedOrder["items_chart"].append(product)
emcoll[1].save(embeddedOrder)
p1ref = dbref.DBRef(recoll[0].name, rp1)
p2ref = dbref.DBRef(recoll[0].name, rp2)
referencedOrder = {"userInfo": "Alex Martinavarro", "items": [p1ref, p2ref]}
referencedOrder = recoll[1].insert(referencedOrder, safe=True)
print "INSERTED PRODUCTS"
printProducts(licoll[0])
printProducts(emcoll[0])
printProducts(recoll[0])
print "ORDERS"
findOrders(licoll[1])
findOrders(emcoll[1])
findOrders(recoll[1])
"""UPDATING"""
updateProducts(licoll[0])
updateProducts(emcoll[0])
updateProducts(recoll[0])
print "UPDATED PRODUCTS"
printProducts(licoll[0])
printProducts(emcoll[0])
printProducts(recoll[0])
print "ORDERS AFTER UPDATE"
findOrders(licoll[1])
findOrders(emcoll[1])
findOrders(recoll[1])
I am answering from the google groups so forgive me if the answer seems off from the one posted above.
“2- Should the “embedded” order reflect the changes in item prices, reflect the change.”
Never, imagine a user places an order and then before it is despatched suddenly realises the price has changed for no apparent reasons. You should duplicate the price upon ordering and place it in the embedded products list. This is what most (if not all) e-commerce sites do.
“The same products are inserted in the products collection, and one order is placed in each order collection, the difference is
the way products are “related” to orders, in one are linked, in other are embedded and the last are referenced.”
Any of the three are valid depending on how the embbeding is done of course. If you are embbeding ordered products within orders then that is fine, embedding orders within products would not be a sound solution. Since I doubt anyone will order enough products to exceed the 16Mb limit you should be safe.
Hope this helps,