def save(self, cname, *jsarr, **kwargs): """ Save/update specified `dict` documents into collection `cname`. Samples: >>> ejdb.save('foo', {'foo' : 'bar'}) >>> ejdb.save('foo', {_id : '511c72ae7922641d00000000', 'foo' : 'bar'}, {'foo' : 'bar2'}, merge=True) >>> ejdb.save('foo', *[{'foo' : 'bar'}, {'foo' : 'bar2'}, ...]) If collection with `cname` does not exists it will be created. Each document may have unique identifier (OID) stored in the `_id` property. If a saved doc does not have `_id` it will be autogenerated, document `dict` object will be updated with this `_id` and new document record will be stored. To identify and update doc it should contains `_id` dict property. :Parameters: - `cname` Collection name - `*jsarr` Variable arg list with doc to be saved - merge=False (optional) If `True` docs with `_id` will be merged with those stored in db, otherwise updated documents will be fully replaced by new instances. """ for doc in jsarr: if doc is not None: _oid = self.__ejdb.save(cname, bson.serialize_to_bytes(doc), **kwargs) if "_id" not in doc: doc["_id"] = _oid
def save(self, cname: str, *jsarr, **kwargs): """ Save/update specified `dict` documents into collection `cname`. Samples: >>> ejdb.save('foo', {'foo' : 'bar'}) >>> ejdb.save('foo', {_id : '511c72ae7922641d00000000', 'foo' : 'bar'}, {'foo' : 'bar2'}, ..., merge=True) >>> ejdb.save('foo', *[{'foo' : 'bar'}, {'foo' : 'bar2'}, ...]) If collection with `cname` does not exists it will be created. Each document may have unique identifier (OID) stored in the `_id` property. If a saved doc does not have `_id` it will be autogenerated, document `dict` object will be updated with this `_id` and new document record will be stored. To identify and update doc it should contains `_id` dict property. :Parameters: - `cname` Collection name - `*jsarr` Variable arg list with doc to be saved - merge=False (optional) If `True` docs with `_id` will be merged with those stored in db, otherwise updated documents will be fully replaced by new instances. """ for doc in jsarr: if doc is not None: _oid = self.__ejdb.save(cname, bson.serialize_to_bytes(doc), **kwargs) if "_id" not in doc: doc["_id"] = _oid
def test_mongo(collection_name): # client, db = None, None # host, port = 'localhost', 27017 # client = MongoClient(host, port) # db = client['groundcontrol'] # collection = db[collection_name] # l = list(collection.find({})) # o = convert_mongo_id(l[0]) ejdb = pyejdb.EJDB("zoo.dat", pyejdb.DEFAULT_OPEN_MODE) # ejdb.save("test_collection", o) print(ejdb.dbmeta()) with ejdb.find("test_collection", {}) as cur: print("found %s parrots" % len(cur)) for p in cur: print('------------------') d2 = parse_bytes(serialize_to_bytes(p)) print(d2) d2 = convert_mongo_id(d2) print(d2['_id']) # print(json.dumps(convert_mongo_id(d2), ensure_ascii=False, indent=4)) # print(by.decode(encoding='utf-8')) # for k in p: # print('{0}='.format(k), p[k]) # print("%s likes toys!" % p["name"]) ejdb.close()
def command(self, cmd): """ Executes ejdb database command. Supported commands: 1) Exports database collections data. See ejdbexport() method. "export" : { "path" : string, //Exports database collections data "cnames" : [string array]|null, //List of collection names to export "mode" : int|null //Values: null|`JBJSONEXPORT` See ejdb.h#ejdbexport() method } Command response: { "log" : string, //Diagnostic log about executing this command "error" : string|null, //ejdb error message "errorCode" : int|0, //ejdb error code } 2) Imports previously exported collections data into ejdb. "import" : { "path" : string //The directory path in which data resides "cnames" : [string array]|null, //List of collection names to import "mode" : int|null //Values: null| JBIMPORTUPDATE`|`JBIMPORTREPLACE` See ejdb.h#ejdbimport() method } Command response: { "log" : string, //Diagnostic log about executing this command "error" : string|null, //ejdb error message "errorCode" : int|0, //ejdb error code } :Parameters: - `cmd` Command object dictionary :Returns: Command response object dictionary """ bret = self.__ejdb.command(bson.serialize_to_bytes(cmd)) if bret is not None: return bson.parse_bytes(bret) return None
def find(self, cname, qobj=None, *args, **kwargs): """ Execute query on collection. Sample: >>> # Fetch all elements from collection >>> ejdb.find("mycoll") >>> # Query document with 'foo==bar' condition, include in resulting doc 'foo' and '_id' fields only >>> ejdb.find("mycoll", {'foo' : 'bar'}, hints={$fields : {'foo' : 1, '_id' : 1}}); General format: find(<collection name>, <query object>, <OR joined query objects>,..., hints=<Query Hints>) :Parameters: - `cname` Collection name - `qobj` Main query object - *args OR joined query object - hints={} (optional) Query hints. See explanations below. - log=StringIO (optional) StringIO buffer for ejdb query log (debugging mode) :Returns: Resultset cursor :class:`EJDBCursorWrapper` EJDB queries inspired by MongoDB (mongodb.org) and follows same philosophy. - Supported queries: - Simple matching of String OR Number OR Array value: - {'fpath' : 'val', ...} - $not Negate operation. - {'fpath' : {'$not' : val}} //Field not equal to val - {'fpath' : {'$not' : {'$begin' : prefix}}} //Field not begins with val - $begin String starts with prefix - {'fpath' : {'$begin' : prefix}} - $gt, $gte (>, >=) and $lt, $lte for number types: - {'fpath' : {'$gt' : number}, ...} - $bt Between for number types: - {'fpath' : {'$bt' : [num1, num2]}} - $in String OR Number OR Array val matches to value in specified array: - {'fpath' : {'$in' : [val1, val2, val3]}} - $nin - Not IN - $strand String tokens OR String array val matches all tokens in specified array: - {'fpath' : {'$strand' : [val1, val2, val3]}} - $stror String tokens OR String array val matches any token in specified array: - {'fpath' : {'$stror' : [val1, val2, val3]}} - $exists Field existence matching: - {'fpath' : {'$exists' : true|false}} - $icase Case insensitive string matching: - {'fpath' : {'$icase' : 'val1'}} //icase matching icase matching with '$in' operation: - {'name' : {'$icase' : {'$in' : ['tHéâtre - театр', 'heLLo WorlD']}}} For case insensitive matching you can create special type of string index. - $elemMatch The $elemMatch operator matches more than one component within an array element. - { array: { $elemMatch: { value1 : 1, value2 : { $gt: 1 } } } } Restriction: only one $elemMatch allowed in context of one array field. - $and, $or joining: - {..., $and : [subq1, subq2, ...] } - {..., $or : [subq1, subq2, ...] } Example: {z : 33, $and : [ {$or : [{a : 1}, {b : 2}]}, {$or : [{c : 5}, {d : 7}]} ] } - Queries can be used to update records: - $set Field set operation. - {.., '$set' : {'field1' : val1, 'fieldN' : valN}} - $upsert Atomic upsert. If matching records are found it will be '$set' operation, otherwise new record will be inserted with fields specified by argment object. - {.., '$upsert' : {'field1' : val1, 'fieldN' : valN}} - $inc Increment operation. Only number types are supported. - {.., '$inc' : {'field1' : number, ..., 'field1' : number} - $dropall In-place record removal operation. - {.., '$dropall' : True} - $addToSet Atomically adds value to the array only if its not in the array already. If containing array is missing it will be created. - {.., '$addToSet' : {'fpath' : val1, 'fpathN' : valN, ...}} - $addToSetAll Batch version if $addToSet - {.., '$addToSetAll' : {'fpath' : [array of values to add], ...}} - $pull Atomically removes all occurrences of value from field, if field is an array. - {.., '$pull' : {'fpath' : val1, 'fpathN' : valN, ...}} - $pullAll Batch version of $pull - {.., '$pullAll' : {'fpath' : [array of values to remove], ...}} - Collection joins supported in the following form: - {..., $do : {fpath : {$join : 'collectionname'}} } Where 'fpath' value points to object's OIDs from 'collectionname'. Its value can be OID, string representation of OID or array of this pointers. .. NOTE:: It is better to execute update queries with `$onlycount=true` hint flag or use the special `update()` method to avoid unnecessarily data fetching. .. NOTE:: Negate operations: $not and $nin not using indexes so they can be slow in comparison to other matching operations. .. NOTE:: Only one index can be used in search query operation. QUERY HINTS (specified by `hints=` argument): - $max Maximum number in the result set - $skip Number of skipped results in the result set - $orderby Sorting order of query fields. - $onlycount true|false If `true` only count of matching records will be returned without placing records in result set. - $fields Set subset of fetched fields. If field presented in $orderby clause it will be forced to include in resulting records. Example: hints: { "$orderby" : [ //ORDER BY field1 ASC, field2 DESC ("field1", 1), ("field2", -1) ], "$fields" : { //SELECT ONLY {_id, field1, field2} "field1" : 1, "field2" : 1 } } """ if not qobj: qobj = {} qobj = bson.serialize_to_bytes(qobj) hints = bson.serialize_to_bytes(self.__preprocessQHints(kwargs.get("hints", {}))) orarr = [bson.serialize_to_bytes(x) for x in args] qflags = kwargs.get("qflags", 0) log = kwargs.get("log") log = log if isinstance(log, StringIO) or isinstance(log, BytesIO) else None cursor = self.__ejdb.find(cname, qobj, orarr, hints, qflags, log) return cursor if isinstance(cursor, numbers.Number) else EJDBCursorWrapper(cursor)
def find(self, cname: str, qobj: optional(dict) = None, *args, **kwargs): """ Execute query on collection. Sample: >>> # Fetch all elements from collection >>> ejdb.find("mycoll") >>> # Query document with 'foo==bar' condition, include in resulting doc 'foo' and '_id' fields only >>> ejdb.find("mycoll", {'foo' : 'bar'}, hints={$fields : {'foo' : 1, '_id' : 1}}); General format: find(<collection name>, <query object>, <OR joined query objects>,..., hints=<Query Hints>) :Parameters: - `cname` Collection name - `qobj` Main query object - *args OR joined query object - hints={} (optional) Query hints. See explanations below. - log=StringIO (optional) StringIO buffer for ejdb query log (debugging mode) :Returns: Resultset cursor :class:`EJDBCursorWrapper` EJDB queries inspired by MongoDB (mongodb.org) and follows same philosophy. - Supported queries: - Simple matching of String OR Number OR Array value: - {'fpath' : 'val', ...} - $not Negate operation. - {'fpath' : {'$not' : val}} //Field not equal to val - {'fpath' : {'$not' : {'$begin' : prefix}}} //Field not begins with val - $begin String starts with prefix - {'fpath' : {'$begin' : prefix}} - $gt, $gte (>, >=) and $lt, $lte for number types: - {'fpath' : {'$gt' : number}, ...} - $bt Between for number types: - {'fpath' : {'$bt' : [num1, num2]}} - $in String OR Number OR Array val matches to value in specified array: - {'fpath' : {'$in' : [val1, val2, val3]}} - $nin - Not IN - $strand String tokens OR String array val matches all tokens in specified array: - {'fpath' : {'$strand' : [val1, val2, val3]}} - $stror String tokens OR String array val matches any token in specified array: - {'fpath' : {'$stror' : [val1, val2, val3]}} - $exists Field existence matching: - {'fpath' : {'$exists' : true|false}} - $icase Case insensitive string matching: - {'fpath' : {'$icase' : 'val1'}} //icase matching icase matching with '$in' operation: - {'name' : {'$icase' : {'$in' : ['tHéâtre - театр', 'heLLo WorlD']}}} For case insensitive matching you can create special type of string index. - $elemMatch The $elemMatch operator matches more than one component within an array element. - { array: { $elemMatch: { value1 : 1, value2 : { $gt: 1 } } } } Restriction: only one $elemMatch allowed in context of one array field. - Queries can be used to update records: - $set Field set operation. - {.., '$set' : {'field1' : val1, 'fieldN' : valN}} - $upsert Atomic upsert. If matching records are found it will be '$set' operation, otherwise new record will be inserted with fields specified by argment object. - {.., '$upsert' : {'field1' : val1, 'fieldN' : valN}} - $inc Increment operation. Only number types are supported. - {.., '$inc' : {'field1' : number, ..., 'field1' : number} - $dropall In-place record removal operation. - {.., '$dropall' : true} - $addToSet Atomically adds value to the array only if its not in the array already. If containing array is missing it will be created. - {.., '$addToSet' : {'fpath' : val1, 'fpathN' : valN, ...}} - $addToSetAll Batch version if $addToSet - {.., '$addToSetAll' : {'fpath' : [array of values to add], ...}} - $pull Atomically removes all occurrences of value from field, if field is an array. - {.., '$pull' : {'fpath' : val1, 'fpathN' : valN, ...}} - $pullAll Batch version of $pull - {.., '$pullAll' : {'fpath' : [array of values to remove], ...}} - Collection joins supported in the following form: - {..., $do : {fpath : {$join : 'collectionname'}} } Where 'fpath' value points to object's OIDs from 'collectionname'. Its value can be OID, string representation of OID or array of this pointers. .. NOTE:: It is better to execute update queries with `$onlycount=true` hint flag or use the special `update()` method to avoid unnecessarily data fetching. .. NOTE:: Negate operations: $not and $nin not using indexes so they can be slow in comparison to other matching operations. .. NOTE:: Only one index can be used in search query operation. QUERY HINTS (specified by `hints=` argument): - $max Maximum number in the result set - $skip Number of skipped results in the result set - $orderby Sorting order of query fields. - $onlycount true|false If `true` only count of matching records will be returned without placing records in result set. - $fields Set subset of fetched fields. If field presented in $orderby clause it will be forced to include in resulting records. Example: hints: { "$orderby" : [ //ORDER BY field1 ASC, field2 DESC ("field1", 1), ("field2", -1) ], "$fields" : { //SELECT ONLY {_id, field1, field2} "field1" : 1, "field2" : 1 } } """ if not qobj: qobj = {} qobj = bson.serialize_to_bytes(qobj) hints = bson.serialize_to_bytes( self.__preprocessQHints(kwargs.get("hints", {}))) orarr = [bson.serialize_to_bytes(x) for x in args] qflags = kwargs.get("qflags", 0) log = kwargs.get("log") log = log if isinstance(log, strio) else None cursor = self.__ejdb.find(cname, qobj, orarr, hints, qflags, log) return cursor if isinstance( cursor, numbers.Number) else EJDBCursorWrapper(cursor)