aggregate.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. "use strict";
  2. var assert = require("assert"),
  3. aggregate = require("../../");
  4. module.exports = {
  5. "aggregate": {
  6. "should be able to use an empty pipeline (no-op)": function(next){
  7. var i = [1, 2, 3],
  8. p = [],
  9. e = [1, 2, 3],
  10. aggregater = aggregate(p);
  11. aggregater(i, function(err, results){
  12. var a = results;
  13. assert.equal(JSON.stringify(a), JSON.stringify(e), "Unexpected value!");
  14. assert.deepEqual(a, e, "Unexpected value (not deepEqual)!");
  15. aggregater(i, function(err, results){
  16. assert.equal(JSON.stringify(results), JSON.stringify(e), "Reuse of aggregater should yield the same results!");
  17. aggregate(p, i, function(err, results){
  18. assert.equal(JSON.stringify(results), JSON.stringify(e), "Alternate use of aggregate should yield the same results!");
  19. next();
  20. });
  21. });
  22. });
  23. },
  24. "should be able to use a $limit operator": function(next){
  25. var i = [{_id:0}, {_id:1}, {_id:2}, {_id:3}, {_id:4}, {_id:5}],
  26. p = [{$limit:2}],
  27. e = [{_id:0}, {_id:1}],
  28. aggregater = aggregate(p);
  29. aggregater(i, function(err, results){
  30. var a = results;
  31. assert.equal(JSON.stringify(a), JSON.stringify(e), "Unexpected value!");
  32. assert.deepEqual(a, e, "Unexpected value (not deepEqual)!");
  33. aggregater(i, function(err, results){
  34. assert.equal(JSON.stringify(results), JSON.stringify(e), "Reuse of aggregater should yield the same results!");
  35. aggregate(p, i, function(err, results){
  36. assert.equal(JSON.stringify(results), JSON.stringify(e), "Alternate use of aggregate should yield the same results!");
  37. next();
  38. });
  39. });
  40. });
  41. },
  42. "should be able to use a $match operator": function(next){
  43. var i = [{_id:0, e:1}, {_id:1, e:0}, {_id:2, e:1}, {_id:3, e:0}, {_id:4, e:1}, {_id:5, e:0}],
  44. p = [{$match:{e:1}}],
  45. e = [{_id:0, e:1}, {_id:2, e:1}, {_id:4, e:1}],
  46. aggregater = aggregate(p);
  47. aggregater(i, function(err, results){
  48. var a = results;
  49. assert.equal(JSON.stringify(a), JSON.stringify(e), "Unexpected value!");
  50. assert.deepEqual(a, e, "Unexpected value (not deepEqual)!");
  51. aggregater(i, function(err, results){
  52. assert.equal(JSON.stringify(results), JSON.stringify(e), "Reuse of aggregater should yield the same results!");
  53. aggregate(p, i, function(err, results){
  54. assert.equal(JSON.stringify(results), JSON.stringify(e), "Alternate use of aggregate should yield the same results!");
  55. next();
  56. });
  57. });
  58. });
  59. },
  60. "should be able to use a $skip operator": function(next){
  61. var i = [{_id:0}, {_id:1}, {_id:2}, {_id:3}, {_id:4}, {_id:5}],
  62. p = [{$skip:2}, {$skip:1}], //testing w/ 2 ensures independent state variables
  63. e = [{_id:3}, {_id:4}, {_id:5}],
  64. aggregater = aggregate(p);
  65. aggregater(i, function(err, results){
  66. var a = results;
  67. assert.equal(JSON.stringify(a), JSON.stringify(e), "Unexpected value!");
  68. assert.deepEqual(a, e, "Unexpected value (not deepEqual)!");
  69. aggregater(i, function(err, results){
  70. assert.equal(JSON.stringify(results), JSON.stringify(e), "Reuse of aggregater should yield the same results!");
  71. aggregate(p, i, function(err, results){
  72. assert.equal(JSON.stringify(results), JSON.stringify(e), "Alternate use of aggregate should yield the same results!");
  73. next();
  74. });
  75. });
  76. });
  77. },
  78. "should be able to use a $skip and then a $limit operator together in the same pipeline": function(next){
  79. var i = [{_id:0, e:1}, {_id:1, e:0}, {_id:2, e:1}, {_id:3, e:0}, {_id:4, e:1}, {_id:5, e:0}],
  80. p = [{$skip:2}, {$limit:1}],
  81. e = [{_id:2, e:1}],
  82. aggregater = aggregate(p);
  83. aggregater(i, function(err, results){
  84. var a = results;
  85. assert.equal(JSON.stringify(a), JSON.stringify(e), "Unexpected value!");
  86. assert.deepEqual(a, e, "Unexpected value (not deepEqual)!");
  87. aggregater(i, function(err, results){
  88. assert.equal(JSON.stringify(results), JSON.stringify(e), "Reuse of aggregater should yield the same results!");
  89. aggregate(p, i, function(err, results){
  90. assert.equal(JSON.stringify(results), JSON.stringify(e), "Alternate use of aggregate should yield the same results!");
  91. next();
  92. });
  93. });
  94. });
  95. },
  96. "should be able to construct an instance with $unwind operators properly": function(next){
  97. var i = [
  98. {_id:0, nodes:[
  99. {one:[11], two:[2,2]},
  100. {one:[1,1], two:[22]}
  101. ]},
  102. {_id:1, nodes:[
  103. {two:[22], three:[333]},
  104. {one:[1], three:[3,3,3]}
  105. ]}
  106. ],
  107. p = [{$unwind:"$nodes"}, {$unwind:"$nodes.two"}],
  108. e = [
  109. {_id:0,nodes:{one:[11],two:2}},
  110. {_id:0,nodes:{one:[11],two:2}},
  111. {_id:0,nodes:{one:[1,1],two:22}},
  112. {_id:1,nodes:{two:22,three:[333]}}
  113. ],
  114. aggregater = aggregate(p);
  115. aggregater(i, function(err, results){
  116. var a = results;
  117. assert.equal(JSON.stringify(a), JSON.stringify(e), "Unexpected value!");
  118. assert.deepEqual(a, e, "Unexpected value (not deepEqual)!");
  119. aggregater(i, function(err, results){
  120. assert.equal(JSON.stringify(results), JSON.stringify(e), "Reuse of aggregater should yield the same results!");
  121. aggregate(p, i, function(err, results){
  122. assert.equal(JSON.stringify(results), JSON.stringify(e), "Alternate use of aggregate should yield the same results!");
  123. next();
  124. });
  125. });
  126. });
  127. },
  128. "should be able to use a $project operator": function(next){
  129. var i = [{_id:0, e:1, f:23}, {_id:2, e:2, g:34}, {_id:4, e:3}],
  130. p = [{$project:{
  131. e:1,
  132. a:{$add:["$e", "$e"]},
  133. b:{$cond:[{$eq:["$e", 2]}, "two", "not two"]}
  134. //TODO: high level test of all other expression operators
  135. }}],
  136. e = [{_id:0, e:1, a:2, b:"not two"}, {_id:2, e:2, a:4, b:"two"}, {_id:4, e:3, a:6, b:"not two"}],
  137. aggregater = aggregate(p);
  138. aggregater(i, function(err, results){
  139. var a = results;
  140. assert.equal(JSON.stringify(a), JSON.stringify(e), "Unexpected value!");
  141. assert.deepEqual(a, e, "Unexpected value (not deepEqual)!");
  142. aggregater(i, function(err, results){
  143. assert.equal(JSON.stringify(results), JSON.stringify(e), "Reuse of aggregater should yield the same results!");
  144. aggregate(p, i, function(err, results){
  145. assert.equal(JSON.stringify(results), JSON.stringify(e), "Alternate use of aggregate should yield the same results!");
  146. next();
  147. });
  148. });
  149. });
  150. },
  151. "should be able to use a $project operator to exclude the _id field": function(next){
  152. var i = [{_id:0, e:1, f:23}, {_id:2, e:2, g:34}, {_id:4, e:3}],
  153. p = [{$project:{
  154. _id:0,
  155. e:1
  156. //TODO: high level test of all other expression operators
  157. }}],
  158. e = [{e:1}, {e:2}, {e:3}],
  159. aggregater = aggregate(p);
  160. aggregater(i, function(err, results){
  161. var a = results;
  162. assert.equal(JSON.stringify(a), JSON.stringify(e), "Unexpected value!");
  163. assert.deepEqual(a, e, "Unexpected value (not deepEqual)!");
  164. aggregater(i, function(err, results){
  165. assert.equal(JSON.stringify(results), JSON.stringify(e), "Reuse of aggregater should yield the same results!");
  166. aggregate(p, i, function(err, results){
  167. assert.equal(JSON.stringify(results), JSON.stringify(e), "Alternate use of aggregate should yield the same results!");
  168. next();
  169. });
  170. });
  171. });
  172. },
  173. "should be able to construct an instance with $sort operators properly (ascending)": function(next){
  174. var i = [
  175. {_id:3.14159}, {_id:-273.15},
  176. {_id:42}, {_id:11}, {_id:1},
  177. {_id:null}, {_id:NaN}
  178. ],
  179. p = [{$sort:{_id:1}}],
  180. e = [
  181. {_id:null}, {_id:NaN},
  182. {_id:-273.15}, {_id:1}, {_id:3.14159}, {_id:11}, {_id:42}
  183. ],
  184. aggregater = aggregate(p);
  185. aggregater(i, function(err, results){
  186. var a = results;
  187. assert.equal(JSON.stringify(a), JSON.stringify(e), "Unexpected value!");
  188. aggregater(i, function(err, results){
  189. assert.equal(JSON.stringify(results), JSON.stringify(e), "Reuse of aggregater should yield the same results!");
  190. aggregate(p, i, function(err, results){
  191. assert.equal(JSON.stringify(results), JSON.stringify(e), "Alternate use of aggregate should yield the same results!");
  192. next();
  193. });
  194. });
  195. });
  196. },
  197. "should be able to construct an instance with $group operators properly": function(next){
  198. var i = [
  199. {_id:0, a:1},
  200. {_id:0, a:2},
  201. {_id:0, a:3},
  202. {_id:0, a:4},
  203. {_id:0, a:1.5},
  204. {_id:0, a:null},
  205. {_id:1, b:"a"},
  206. {_id:1, b:"b"},
  207. {_id:1, b:"b"},
  208. {_id:1, b:"c"}
  209. ],
  210. p = [{$group:{
  211. _id:"$_id",
  212. sum_a:{$sum:"$a"},
  213. //min_a:{$min:"$a"}, //this is busted in this version of mongo
  214. max_a:{$max:"$a"},
  215. avg_a:{$avg:"$a"},
  216. first_b:{$first:"$b"},
  217. last_b:{$last:"$b"},
  218. addToSet_b:{$addToSet:"$b"},
  219. push_b:{$push:"$b"}
  220. }}],
  221. e = [
  222. {
  223. _id:0,
  224. sum_a:11.5,
  225. //min_a:1,
  226. max_a:4,
  227. avg_a:2.3,
  228. first_b:undefined,
  229. last_b:undefined,
  230. addToSet_b:[],
  231. push_b:[]
  232. },
  233. {
  234. _id:1,
  235. sum_a:0,
  236. //min_a:null,
  237. max_a:undefined,
  238. avg_a:0,
  239. first_b:"a",
  240. last_b:"c",
  241. addToSet_b:["a", "b", "c"],
  242. push_b:["a", "b", "b", "c"]
  243. }
  244. ],
  245. aggregater = aggregate(p);
  246. aggregater(i, function(err, results){
  247. var a = results;
  248. assert.equal(JSON.stringify(a), JSON.stringify(e), "Unexpected value!");
  249. assert.deepEqual(a, e, "Unexpected value (not deepEqual)!");
  250. aggregater(i, function(err, results){
  251. assert.equal(JSON.stringify(results), JSON.stringify(e), "Reuse of aggregater should yield the same results!");
  252. aggregate(p, i, function(err, results){
  253. assert.equal(JSON.stringify(results), JSON.stringify(e), "Alternate use of aggregate should yield the same results!");
  254. next();
  255. });
  256. });
  257. });
  258. },
  259. "should be able to construct an instance with $group using concat": function(next){
  260. var i = [
  261. {_id:0, a:null},
  262. {_id:1, a:"a"},
  263. {_id:1, a:"b"},
  264. {_id:1, a:"b"},
  265. {_id:1, a:"c"}
  266. ],
  267. p = [{$group:{
  268. _id:{$concat:["$a"]},
  269. }}],
  270. e = [
  271. {
  272. _id:null,
  273. },
  274. {
  275. _id:"a",
  276. },
  277. {
  278. _id:"b",
  279. },
  280. {
  281. _id:"c",
  282. }
  283. ],
  284. aggregater = aggregate(p);
  285. aggregater(i, function(err, results){
  286. var a = results;
  287. assert.equal(JSON.stringify(a), JSON.stringify(e), "Unexpected value!");
  288. assert.deepEqual(a, e, "Unexpected value (not deepEqual)!");
  289. aggregater(i, function(err, results){
  290. assert.equal(JSON.stringify(results), JSON.stringify(e), "Reuse of aggregater should yield the same results!");
  291. aggregate(p, i, function(err, results){
  292. assert.equal(JSON.stringify(results), JSON.stringify(e), "Alternate use of aggregate should yield the same results!");
  293. next();
  294. });
  295. });
  296. });
  297. }
  298. }
  299. };
  300. if(!module.parent) (new (require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run();