def save_order(self, order): ''' Lab 3: K/V operation(s): 1. generate key: order_<orderId> 2. insert order: collection.insert(key, document) 3. IF successful insert, GET order ''' try: order_id = self.get_next_order_id() key = 'order_{0}'.format(order_id + 1) order['_id'] = key order['orderId'] = order_id + 1 order['doc']['created'] = int(datetime.datetime.now().timestamp()) order['doc']['createdBy'] = order['custId'] saved = self.__collection.insert(key, order) if not saved: return {'order': None, 'error': 'Unable to save order.'} saved_order = self.get_object_by_key(key) return {'order': saved_order['result'], 'error': None} except Exception as ex: output_message(ex, 'repository.py:save_order() - error:') return { 'order': None, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def search_products(self, product, fuzziness): """ Lab 2: Search operation (FTS) 1. FTS: term query w/ fuzziness use "basic-search" as index name for searchQuery 2. K/V getMulti() using FTS results """ try: result = self.__cluster.search_query( 'basic-search', TermQuery(term=product, fuzziness=fuzziness) if fuzziness else TermQuery(term=product), SearchOptions(limit=100)) doc_ids = list(map(lambda r: r.id, result)) # TODO: 2020.11.16 - get_multi() doesn't work, LCB_ERR_UNSUPPORTED_OPERATION (214) thrown # product_docs = self.__cluster.get_multi(doc_ids) # TODO: This is slow, just looping over the ids and fetch on each on # need to work in an async approach products = list( map(lambda id: self.get_object_by_key(id)['result'], doc_ids)) return {'products': products, 'error': None} except Exception as ex: output_message(ex, 'repository.py:search_products() - error:') return { 'products': None, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def udpate_address(self, cust_id, path, address): ''' Lab 5: K/V sub-document operation(s): 1. generate key: customer_<custId> 2. update customer document address path 3. update customer document modified date and modifiedBy When updating, think about pros/cons to UPSERT v. REPLACE ''' try: key = 'customer_{0}'.format(cust_id) modified_date = int(datetime.datetime.now().timestamp()) self.__collection.mutate_in(key, [ SD.upsert(path, address), SD.upsert('doc.modified', modified_date), SD.upsert('doc.modifiedby', cust_id), ]) return {'success': True, 'error': None} except Exception as ex: output_message(ex, 'repository.py:udpate_address() - error:') return { 'success': False, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def get_user_info(self, username): try: n1ql = """ SELECT c.custId, u.userId, u.username, u.`password` FROM `{0}` u JOIN `{0}` c ON c.username = u.username AND c.doc.type = 'customer' WHERE u.docType ='user' AND u.username = $1 ORDER BY u.userId DESC LIMIT 1; """.format(self.bucket_name) params = [username] opts = QueryOptions(positional_parameters=params) result = self.__cluster.query(n1ql, opts) user = next((u for u in result.rows() if u is not None), None) return {'user_info': user, 'error': None} except Exception as ex: output_message(ex, 'repository.py:get_user_info() - error:') return { 'user_info': None, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def save_address(self, cust_id, path, address): ''' Lab 5: K/V sub-document operation(s): 1. generate key: customer_<custId> 2. get customer addresses 3. create business logic to add new address 4. update customer address path 5. update customer modified date and modifiedBy When updating, think about pros/cons to UPSERT v. REPLACE ''' try: #TODO - figure out what SD.exists returns False, although SD.get returns a doc key = 'customer_{0}'.format(cust_id) result = self.__collection.lookup_in( key, [ #SD.exists(path), SD.get(path) ]) #if not result.content_as[bool](0) or result.content_as[dict](1) is None: if result.content_as[dict](0) is None: return {'success': False, 'error': None} addresses = result.content_as[dict](0) addresses[address['name']] = { 'address': address['address'], 'city': address['city'], 'state': address['state'], 'zipCode': address['zipCode'], 'country': address['country'] if 'country' in address else 'US', } modified_date = int(datetime.datetime.now().timestamp()) self.__collection.mutate_in(key, [ SD.upsert(path, addresses), SD.upsert('doc.modified', modified_date), SD.upsert('doc.modifiedby', cust_id), ]) return {'success': True, 'error': None} except Exception as ex: output_message(ex, 'repository.py:save_address() - error:') return { 'success': False, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def connect(self): db_config = get_db_config() self.host = db_config['host'] self.bucket_name = db_config['bucket'] self.username = db_config['username'] self.password = db_config['password'] connection_str = 'couchbase://{0}'.format(self.host) if db_config['secure'] == 'true': connection_str = 'couchbases://{0}?ssl=no_verify'.format(self.host) print(connection_str) secure = db_config['secure'] print(secure) try: options = ClusterOptions( PasswordAuthenticator(self.username, self.password)) self.__cluster = Cluster(connection_str, options) self.__bucket = self.__cluster.bucket(self.bucket_name) self.__collection = self.__bucket.default_collection() output_message('repository') if len(self.__bucket.name) > 0: output_message( self.__bucket.name, 'repository.py:connect() - connected to bucket:') else: output_message( 'repository.py:connect() - error connecting to bucket.') except Exception as ex: output_message( ex, 'repository.py:connect() - error connecting to bucket.') raise
def delete_order(self, order_id): ''' Lab 3: K/V operation(s): 1. delete order: cluster.remove(key) ''' try: return 'NOP' except Exception as ex: output_message(ex, 'repository.py:delete_order() - error:') return { 'success': False, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def get_customer(self, id): """ Lab 1: K/V operation - Get 1. Get customer: bucket.get(key) """ try: return 'NOP' except Exception as ex: output_message(ex, 'repository.py:get_customer() - error:') return { 'customer': None, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def get_object_by_key(self, key): try: result = self.__collection.get(key) return {'result': result.content, 'error': None} except Exception as ex: output_message( ex, 'repository.py:get_object_by_key() - error retreiving document: {}' .format(key)) return { 'result': None, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def extend_session(self, sessionId, expiry): try: key = 'session::{0}'.format(sessionId) result = self.__collection.get(key, ttl=expiry) return { 'session': result.content if result else None, 'error': None } except DocumentNotFoundException as ex: output_message(ex, 'repository.py:extend_session() - error:') return { 'session': None, 'error': { 'message': 'Document not found.', 'stackTrace': traceback.format_exc() } }
def replace_order(self, order): ''' Lab 3: K/V operation(s): 1. generate key: order_<orderId> 2. replace order: collection.insert(key, document) ''' try: return 'NOP' except Exception as ex: output_message(ex, 'repository.py:replace_order() - error:') return { 'success': False, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def ping(self): try: result = self.get_object_by_key('customer_0') return { 'result': 'Connected to Couchbase server.' if result['result'] else None, 'error': result['error'] } except Exception as ex: output_message( ex, 'repository.py:ping() - error:') return { 'result': None, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def save_order(self, order): ''' Lab 3: K/V operation(s): 1. generate key: order_<orderId> 2. insert order: collection.insert(key, document) 3. IF successful insert, GET order ''' try: return 'NOP' except Exception as ex: output_message(ex, 'repository.py:save_order() - error:') return { 'order': None, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def create_account(self, user_info): try: customer_doc = self.get_new_customer_document(user_info) saved_customer = self.__collection.insert(customer_doc['_id'], customer_doc) if not saved_customer: return { 'acct': None, 'error': { 'message': 'Unable to save customer document.', 'stackTrace': None } } user_doc = self.get_new_user_document(user_info) saved_user = self.__collection.insert(user_doc['_id'], user_doc) if not saved_user: return { 'acct': None, 'error': { 'message': 'Unable to save user document.', 'stackTrace': None } } user_doc['password'] = None return { 'acct': { 'customerInfo': customer_doc, 'userInfo': user_doc }, 'error': None } except Exception as ex: output_message(ex, 'repository.py:create_account() - error:') return { 'acct': None, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def search_products(self, product, fuzziness): """ Lab 2: Search operation (FTS) 1. FTS: term query w/ fuzziness use "basic-search" as index name for searchQuery 2. K/V getMulti() using FTS results """ try: return 'NOP' except Exception as ex: output_message( ex, 'repository.py:search_products() - error:') return { 'products': None, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() }}
def get_orders(self, customer_id): ''' Lab 4: N1QL operations 1. Get orders for customerId - WHERE order.orderStatus != 'created' - Document properties needed (more can be provided): id, orderStatus, shippingInfo.name aliased as shippedTo, grandTotal, lineItems, orderDate (hint use MILLIS_TO_STR()) ''' try: n1ql = """ SELECT META(o).id, o.orderStatus, o.shippingInfo.name AS shippedTo, o.grandTotal, o.lineItems, MILLIS_TO_STR(o.orderDate) AS orderDate FROM `{0}` o WHERE o.doc.type = 'order' AND o.custId=$1 ORDER BY o.orderDate DESC NULLS FIRST """.format(self.bucket_name) params = [customer_id] # TODO: adhoc, add adhoc=True to QueryOptions opts = QueryOptions(positional_parameters=params) result = self.__cluster.query(n1ql, opts) return {'orders': result.rows(), 'error': None} except Exception as ex: output_message(ex, 'repository.py:get_orders() - error:') return { 'order': False, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def create_session(self, username, expiry): try: session = { 'sessionId': str(uuid.uuid4()), 'username': username, 'docType': 'SESSION' } key = 'session::{0}'.format(session['sessionId']) result = self.__collection.insert(key, session, ttl=expiry) return {'session_id': session['sessionId'] if result else None, 'error': None} except Exception as ex: output_message( ex, 'repository.py:create_session() - error:') return { 'session_id': None, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() }}
def get_order(self, order_id): ''' Lab 3: K/V operation(s): 1. get order: cluster.get(key) ''' try: result = self.__collection.get(order_id) return { 'order': result.content if result is not None and result.content is not None else None, 'error': None } except Exception as ex: output_message( ex, 'repository.py:get_order() - error:') return { 'order': False, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() }}
def udpate_address(self, cust_id, path, address): ''' Lab 5: K/V sub-document operation(s): 1. generate key: customer_<custId> 2. update customer document address path 3. update customer document modified date and modifiedBy When updating, think about pros/cons to UPSERT v. REPLACE ''' try: return 'NOP' except Exception as ex: output_message(ex, 'repository.py:udpate_address() - error:') return { 'success': False, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def replace_order(self, order): ''' Lab 3: K/V operation(s): 1. generate key: order_<orderId> 2. replace order: collection.insert(key, document) ''' try: key = 'order_{0}'.format(order['orderId']) order['doc']['modified'] = int(datetime.datetime.now().timestamp()) order['doc']['modifiedBy'] = order['custId'] saved = self.__collection.replace(key, order) return {'success': saved is not None, 'error': None} except Exception as ex: output_message(ex, 'repository.py:replace_order() - error:') return { 'success': False, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def get_new_order(self, customer_id): ''' Lab 4: N1QL operations 1. Get latest order for customerId - WHERE order.orderStatus = 'created' - Document properties needed (more can be provided): doc, custId, orderStatus, billingInfo, shippingInfo, shippingTotal, tax, lineItems, grandTotal, orderId, _id ''' try: n1ql = """ SELECT o.doc, o.custId, o.orderStatus, o.billingInfo, o.shippingInfo, o.shippingTotal, o.tax, o.lineItems, o.grandTotal, o.orderId, o._id FROM `{0}` o WHERE o.doc.type = 'order' AND o.custId=$1 AND o.orderStatus = 'created' ORDER BY o.orderDate DESC NULLS FIRST LIMIT 1; """.format(self.bucket_name) params = [customer_id] # TODO: adhoc, add adhoc=True to QueryOptions opts = QueryOptions(positional_parameters=params) result = self.__cluster.query(n1ql, opts) return {'order': result.rows(), 'error': None} except Exception as ex: output_message(ex, 'repository.py:get_new_order() - error:') return { 'order': False, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def get_new_order(self, customer_id): ''' Lab 4: N1QL operations 1. Get latest order for customerId - WHERE order.orderStatus = 'created' - Document properties needed (more can be provided): doc, custId, orderStatus, billingInfo, shippingInfo, shippingTotal, tax, lineItems, grandTotal, orderId, _id ''' try: return 'NOP' except Exception as ex: output_message(ex, 'repository.py:get_new_order() - error:') return { 'order': False, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }
def get_orders(self, customer_id): ''' Lab 4: N1QL operations 1. Get orders for customerId - WHERE order.orderStatus != 'created' - Document properties needed (more can be provided): id, orderStatus, shippingInfo.name aliased as shippedTo, grandTotal, lineItems, orderDate (hint use MILLIS_TO_STR()) ''' try: return 'NOP' except Exception as ex: output_message(ex, 'repository.py:get_orders() - error:') return { 'order': False, 'error': { 'message': repr(ex), 'stackTrace': traceback.format_exc() } }