1 | # btrz-simple-dao
|
2 |
|
3 | A **very simple** DAO for MongoDb.
|
4 | Compatible with NodeJS versions 6.11.1 and higher.
|
5 |
|
6 |
|
7 | ## Change log
|
8 | See releases
|
9 |
|
10 | ## General usage
|
11 |
|
12 | The api is very simple and fluent.
|
13 |
|
14 | simpleDao
|
15 | .for(Account)
|
16 | .find({})
|
17 | .toArray()
|
18 | .then(function (results) {
|
19 | // do somethig with the results;
|
20 | })
|
21 | .catch(function (err) {
|
22 | // we crashed
|
23 | });
|
24 |
|
25 | If you are working in a promise based solution you can just return.
|
26 |
|
27 | return simpleDao
|
28 | .for(Account)
|
29 | .find({})
|
30 | .toArray();
|
31 |
|
32 | Or if you much rather use a stream (changed API on 2.0 toCursor returns a promise as well)
|
33 |
|
34 | simpleDao
|
35 | .for(Account)
|
36 | .find({})
|
37 | .toCursor()
|
38 | .then((cursor) => {
|
39 | cursor.on("data", function (datum) {
|
40 | // do work
|
41 | })
|
42 | .on("end", function () {
|
43 | //we are done
|
44 | })
|
45 | .on("error", function (err) {
|
46 | //we crashed
|
47 | });
|
48 | });
|
49 |
|
50 | ## Api
|
51 |
|
52 | ### new SimpleDao(config, logger)
|
53 |
|
54 | Changed in v2.0 we added the logger non mandatory parameter.
|
55 | Logger is expected to implement the `.info` and `.error` methods.
|
56 |
|
57 | Creates a new instance of a simple dao.
|
58 | The `config` argument is expected to have the form.
|
59 |
|
60 | config = {
|
61 | db: {
|
62 | options: {
|
63 | database: "simple_dao_test",
|
64 | username: "",
|
65 | password: ""
|
66 | },
|
67 | uris: ["127.0.0.1:27017"]
|
68 | }
|
69 | };
|
70 |
|
71 | ### .for(Model)
|
72 |
|
73 | Returns an instance of a `Operator` that will map results to instances of the `Model`
|
74 | The `Model` class is expected to have an static `factory` method.
|
75 | The `Model` class can have an static `collectioName` method that the `Operator` will use to query the collection if the `collectionName` is not found it will use the name of the class (object) in lower case as the name of the collection.
|
76 |
|
77 | let operator = simpleDao.for(Account);
|
78 | //this will query a collection with the name "account"
|
79 |
|
80 | If we want to use a different name, we can create a model with the `collectionName` static function
|
81 |
|
82 | class User {
|
83 |
|
84 | static collectionName() {
|
85 | return "people";
|
86 | }
|
87 |
|
88 | static factory(literal) {
|
89 | var user = new User();
|
90 | user.name = literal.name;
|
91 | //Other mappings transformations go hear.
|
92 | return user;
|
93 | }
|
94 | }
|
95 |
|
96 | let operator = simpleDao.for(User);
|
97 | //In this case it will query a collection with the name "people";
|
98 |
|
99 | ### .aggregate(collectionName, pipeline)
|
100 |
|
101 | This method will return a promise.
|
102 | The promise should resolve to a stream cursor with the result of applying the given `pipeline` unto the collection of the given `collectionName`.
|
103 |
|
104 | let pipeline = [
|
105 | {$group: {_id: "$accountId", totalPop: {$sum: "$dataMapId"}}}
|
106 | ];
|
107 |
|
108 | simpleDao
|
109 | .aggregate("accounts", pipeline)
|
110 | .then(function (cursor) {
|
111 | cursor
|
112 | .on("data", function (datum) {
|
113 | // work with the data
|
114 | })
|
115 | .on("end", function () {
|
116 | //we are done
|
117 | })
|
118 | .on("error", function (err) {
|
119 | //we crashed
|
120 | });
|
121 | });
|
122 |
|
123 | The aggregate method will use the following options when calling the database.
|
124 |
|
125 | {
|
126 | allowDiskUse: true,
|
127 | cursor: {batchSize: 1000}
|
128 | }
|
129 |
|
130 | `allowDiskUse` will prevent errors due to size limits on the results.
|
131 |
|
132 | ### .save(model)
|
133 |
|
134 | It will save the model into a collection for that model (see above on the `for` method to understand how the collection name is set).
|
135 | There is no serialization strategy at the moment so "all" public methods and properties will be saved into the database.
|
136 |
|
137 | ### .dropCollection(name)
|
138 |
|
139 | It will drop the collection from the database.
|
140 |
|
141 | ### .objectId()
|
142 |
|
143 | There are an static and an instance version of the method for convenience.
|
144 | It takes an optional parameter that should be a valid 24 characters id.
|
145 |
|
146 | #### Static version
|
147 |
|
148 | SimpleDao.objectId() //Returns a new ObjectID;
|
149 | SimpleDao.objectId("55b27c2a74757b3c5e121b0e") //Return an ObjectID for that id.
|
150 |
|
151 | #### Instance version
|
152 |
|
153 | let simpleDao = new SimpleDao(config);
|
154 | simpleDao.objectId() //Returns a new ObjectID;
|
155 | simpleDao.objectId("55b27c2a74757b3c5e121b0e") //Return an ObjectID for that id.
|
156 |
|
157 | ### connectionString
|
158 |
|
159 | Is a property that will return the connection string the object is using to connect to Mongo.
|
160 |
|
161 | ### new Operator() //Private
|
162 |
|
163 | The Operator is a private object that is accessed via the `.for` method factory on a SimpleDao instance.
|
164 |
|
165 | ### .count(query)
|
166 |
|
167 | It will perform a `.count` on the collection that the operator have been created for (see above on the `for` method to understand how the collection name is set) with the given `query`.
|
168 | If the query is not provided it will default to a count on the complete collection.
|
169 |
|
170 | simpleDao.for(Account).count({name: "new account"}); //Returns a promise that will resolve to the count of documents matching the query.
|
171 |
|
172 | ### .find(query, options)
|
173 |
|
174 | It will perform a `find` on the collection that the operator have been created for (see above on the `for` method to understand how the collection name is set) with the given `query` and `options`.
|
175 | The query and options are the same as with the node mongodb driver find method.
|
176 |
|
177 | let innerCursor = simpleDao.for(Account).find({}); //Returns an inner cursor with all documents in the account collection.
|
178 |
|
179 | ### .findOne(query)
|
180 |
|
181 | It will perform a `findOne` on the collection that the operator have been created for (see above on the `for` method to understand how the collection name is set) with the given `query`.
|
182 |
|
183 | simpleDao.for(Account).findOne({name: "new account"}); //Returns a promise that will resolve to the document or null (if it can't find one).
|
184 |
|
185 | ### .findById(id)
|
186 |
|
187 | It will perform a `findOne` on the collection that the operator have been created for (see above on the `for` method to understand how the collection name is set) with the query {_id: id}.
|
188 |
|
189 | simpleDao.for(Account).findById(SimpleDao.objectId("55b27c2a74757b3c5e121b0e")); //Returns a promise that will resolve to the document or null (if it can't find one).
|
190 |
|
191 | You can pass anything to the id not just ObjectID, it will depend on what do you use to generate the `_id` in the mongo collections.
|
192 |
|
193 | ### .findAggregate(pipeline)
|
194 |
|
195 | An alternative to the `aggregate` method on SimpleDao, but is meant to be used with `for` method (see above). Same options of `aggregate` applies.
|
196 |
|
197 | let innerCursor = simpleDao.for(Account).findAggregate([{"$match": {...}}, {"$unwind": {...}}, ...]); //Returns an inner cursor with all the aggregates for the account collection.
|
198 |
|
199 | ### .removeById(id)
|
200 |
|
201 | It will perform a `remove` on the collection that the operator have been created for (see above on the `for` method to understand how the collection name is set) with the query {_id: id}.
|
202 |
|
203 | simpleDao.for(Account).removeById(SimpleDao.objectId("55b27c2a74757b3c5e121b0e")); //Returns a promise that will resolve to the remove result: {ok: 1, n: 1} where n is the count of deleted documents.
|
204 |
|
205 | You can pass anything to the id not just ObjectID, it will depend on what do you use to generate the `_id` in the mongo collections.
|
206 |
|
207 | ### .remove(query)
|
208 |
|
209 | It will perform a `remove` on the collection that the operator have been created for (see above on the `for` method to understand how the collection name is set) with the given query.
|
210 |
|
211 | simpleDao.for(Account).remove({name: "super"}); //Returns a promise that will resolve to the remove result: {ok: 1, n: 5} where n is the count of deleted documents.
|
212 |
|
213 | ### .update(query, update, options)
|
214 |
|
215 | It will perform an `update` on the collection that the operator have been created for (see above on the `for` method to understand how the collection name is set) with the given `query`, applying the `update` and `options`.
|
216 | The query, update and options are the same as with the node mongodb driver update method.
|
217 |
|
218 | simpleDao.for(Account).update({name: "new account"}, { $set: {name: "Peter account"}}); //Returns a promise with the result report than the node mongodb driver.
|
219 |
|
220 | ### new innerCursor() //Private
|
221 |
|
222 | The innerCursor is a private object that is accessed via the `.find` method factory on an instance of the Operator.
|
223 | It contains only 2 methods
|
224 |
|
225 | ### .toArray()
|
226 |
|
227 | It will iterate over the results and create instance of the `Model` given to the `.for` method. It will return a promise that will resolve to an array with the results.
|
228 |
|
229 | ### .toCursor()
|
230 |
|
231 | It will return a streaming cursor with the results.
|
232 |
|
233 | ## Mock Simple Dao
|
234 | It is a mock for testing simple-dao that supports all the simple-dao operations.
|
235 | Currently, for find and findAggregate `toCursor()` is not available.
|
236 | ### how to use
|
237 | You can pass a source object specifying the expected result for each operation.
|
238 |
|
239 | const mockSimpleDao = require("btrz-simple-dao").mockSimpleDao;`
|
240 |
|
241 | source = {
|
242 | find: [data],
|
243 | update: {}
|
244 | };
|
245 | mockDao = mockSimpleDao(source);
|
246 |
|
247 | mockDao.find().toArray();
|
248 | // [data]
|