PageRenderTime 55ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/codes-node/todo/node_modules/mongoose/test/query.test.js

http://bukuphpjs.codeplex.com
JavaScript | 1111 lines | 984 code | 118 blank | 9 comment | 4 complexity | 923f8370178c61918794d303808b43c5 MD5 | raw file
Possible License(s): Apache-2.0, MIT, LGPL-2.1
  1. /**
  2. * Module dependencies.
  3. */
  4. var start = require('./common')
  5. , Query = require('../lib/query')
  6. , mongoose = start.mongoose
  7. , DocumentObjectId = mongoose.Types.ObjectId
  8. , Schema = mongoose.Schema
  9. , assert = require('assert')
  10. , random = require('../lib/utils').random
  11. var Comment = new Schema({
  12. text: String
  13. });
  14. var Product = new Schema({
  15. tags: {} // mixed
  16. , array: Array
  17. , ids: [Schema.ObjectId]
  18. , strings: [String]
  19. , numbers: [Number]
  20. , comments: [Comment]
  21. });
  22. mongoose.model('Product', Product);
  23. mongoose.model('Comment', Comment);
  24. /**
  25. * Test.
  26. */
  27. describe('Query', function(){
  28. describe('select', function(){
  29. it('(object)', function(){
  30. var query = new Query();
  31. query.select({a: 1, b: 1, c: 0});
  32. assert.deepEqual(query._fields,{a: 1, b: 1, c: 0});
  33. })
  34. it('(string)', function () {
  35. var query = new Query();
  36. query.select(" a b -c ");
  37. assert.deepEqual(query._fields,{a: 1, b: 1, c: 0});
  38. });
  39. it('("a","b","c")', function(){
  40. assert.throws(function () {
  41. var query = new Query();
  42. query.select('a', 'b', 'c');
  43. }, /Invalid select/);
  44. })
  45. it('["a","b","c"]', function(){
  46. assert.throws(function () {
  47. var query = new Query();
  48. query.select(['a', 'b', 'c']);
  49. }, /Invalid select/);
  50. })
  51. it('should not overwrite fields set in prior calls', function(){
  52. var query = new Query();
  53. query.select('a');
  54. assert.deepEqual(query._fields,{a: 1});
  55. query.select('b');
  56. assert.deepEqual(query._fields,{a: 1, b: 1});
  57. query.select({ c: 0 })
  58. assert.deepEqual(query._fields,{a: 1, b: 1, c: 0});
  59. query.select('-d')
  60. assert.deepEqual(query._fields,{a: 1, b: 1, c: 0, d: 0});
  61. })
  62. })
  63. describe('where', function(){
  64. it('works', function(){
  65. var query = new Query();
  66. query.where('name', 'guillermo');
  67. assert.deepEqual(query._conditions, {name: 'guillermo'});
  68. query.where('a');
  69. query.equals('b');
  70. assert.deepEqual(query._conditions, {name: 'guillermo', a: 'b'});
  71. })
  72. it('throws if non-string path is passed', function(){
  73. var query = new Query();
  74. assert.throws(function () {
  75. query.where({ name: 'aaron'});
  76. });
  77. assert.throws(function () {
  78. query.where(50);
  79. });
  80. assert.throws(function () {
  81. query.where([])
  82. });
  83. })
  84. it('does not throw when 0 args passed', function () {
  85. var query = new Query;
  86. assert.doesNotThrow(function(){
  87. query.where();
  88. });
  89. })
  90. })
  91. describe('equals', function(){
  92. it('works', function(){
  93. var query = new Query();
  94. query.where('name').equals('guillermo');
  95. assert.deepEqual(query._conditions, {name: 'guillermo'});
  96. })
  97. })
  98. describe('gte', function(){
  99. it('with 2 args', function(){
  100. var query = new Query();
  101. query.gte('age', 18);
  102. assert.deepEqual(query._conditions, {age: {$gte: 18}});
  103. })
  104. it('with 1 arg', function(){
  105. var query = new Query();
  106. query.where("age").gte(18);
  107. assert.deepEqual(query._conditions, {age: {$gte: 18}});
  108. })
  109. })
  110. describe('gt', function(){
  111. it('with 1 arg', function(){
  112. var query = new Query();
  113. query.where("age").gt(17);
  114. assert.deepEqual(query._conditions, {age: {$gt: 17}});
  115. })
  116. it('with 2 args', function(){
  117. var query = new Query();
  118. query.gt('age', 17);
  119. assert.deepEqual(query._conditions, {age: {$gt: 17}});
  120. })
  121. })
  122. describe('lte', function(){
  123. it('with 1 arg', function(){
  124. var query = new Query();
  125. query.where("age").lte(65);
  126. assert.deepEqual(query._conditions, {age: {$lte: 65}});
  127. })
  128. it('with 2 args', function(){
  129. var query = new Query();
  130. query.lte('age', 65);
  131. assert.deepEqual(query._conditions, {age: {$lte: 65}});
  132. })
  133. })
  134. describe('lt', function(){
  135. it('with 1 arg', function(){
  136. var query = new Query();
  137. query.where("age").lt(66);
  138. assert.deepEqual(query._conditions, {age: {$lt: 66}});
  139. })
  140. it('with 2 args', function(){
  141. var query = new Query();
  142. query.lt('age', 66);
  143. assert.deepEqual(query._conditions, {age: {$lt: 66}});
  144. })
  145. })
  146. describe('combined', function(){
  147. describe('lt and gt', function(){
  148. var query = new Query();
  149. query.where("age").lt(66).gt(17);
  150. assert.deepEqual(query._conditions, {age: {$lt: 66, $gt: 17}});
  151. })
  152. })
  153. describe('tl on one path and gt on another', function(){
  154. it('works', function(){
  155. var query = new Query();
  156. query
  157. .where("age").lt(66)
  158. .where("height").gt(5);
  159. assert.deepEqual(query._conditions, {age: {$lt: 66}, height: {$gt: 5}});
  160. });
  161. })
  162. describe('ne', function(){
  163. it('with 1 arg', function(){
  164. var query = new Query();
  165. query.where("age").ne(21);
  166. assert.deepEqual(query._conditions, {age: {$ne: 21}});
  167. })
  168. it('with 2 args', function(){
  169. var query = new Query();
  170. query.ne('age', 21);
  171. assert.deepEqual(query._conditions, {age: {$ne: 21}});
  172. })
  173. })
  174. describe('in', function(){
  175. it('with 1 arg', function(){
  176. var query = new Query();
  177. query.where("age").in([21, 25, 30]);
  178. assert.deepEqual(query._conditions, {age: {$in: [21, 25, 30]}});
  179. })
  180. it('with 2 args', function(){
  181. var query = new Query();
  182. query.in('age', [21, 25, 30]);
  183. assert.deepEqual(query._conditions, {age: {$in: [21, 25, 30]}});
  184. })
  185. it('where a non-array value no via where', function(){
  186. var query = new Query();
  187. query.in('age', 21);
  188. assert.deepEqual(query._conditions, {age: {$in: 21}});
  189. })
  190. it('where a non-array value via where', function(){
  191. var query = new Query();
  192. query.where('age').in(21);
  193. assert.deepEqual(query._conditions, {age: {$in: 21}});
  194. })
  195. })
  196. describe('nin', function(){
  197. it('with 1 arg', function(){
  198. var query = new Query();
  199. query.where("age").nin([21, 25, 30]);
  200. assert.deepEqual(query._conditions, {age: {$nin: [21, 25, 30]}});
  201. })
  202. it('with 2 args', function(){
  203. var query = new Query();
  204. query.nin('age', [21, 25, 30]);
  205. assert.deepEqual(query._conditions, {age: {$nin: [21, 25, 30]}});
  206. })
  207. it('with a non-array value not via where', function(){
  208. var query = new Query();
  209. query.nin('age', 21);
  210. assert.deepEqual(query._conditions, {age: {$nin: 21}});
  211. })
  212. it('with a non-array value via where', function(){
  213. var query = new Query();
  214. query.where('age').nin(21);
  215. assert.deepEqual(query._conditions, {age: {$nin: 21}});
  216. })
  217. })
  218. describe('mod', function(){
  219. it('not via where, where [a, b] param', function(){
  220. var query = new Query();
  221. query.mod('age', [5, 2]);
  222. assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
  223. })
  224. it('not via where, where a and b params', function(){
  225. var query = new Query();
  226. query.mod('age', 5, 2);
  227. assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
  228. })
  229. it('via where, where [a, b] param', function(){
  230. var query = new Query();
  231. query.where("age").mod([5, 2]);
  232. assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
  233. })
  234. it('via where, where a and b params', function(){
  235. var query = new Query();
  236. query.where("age").mod(5, 2);
  237. assert.deepEqual(query._conditions, {age: {$mod: [5, 2]}});
  238. })
  239. })
  240. describe('near', function(){
  241. it('via where, where [lat, long] param', function(){
  242. var query = new Query();
  243. query.where('checkin').near([40, -72]);
  244. assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
  245. })
  246. it('via where, where lat and long params', function(){
  247. var query = new Query();
  248. query.where('checkin').near(40, -72);
  249. assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
  250. })
  251. it('not via where, where [lat, long] param', function(){
  252. var query = new Query();
  253. query.near('checkin', [40, -72]);
  254. assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
  255. })
  256. it('not via where, where lat and long params', function(){
  257. var query = new Query();
  258. query.near('checkin', 40, -72);
  259. assert.deepEqual(query._conditions, {checkin: {$near: [40, -72]}});
  260. })
  261. })
  262. describe('nearSphere', function(){
  263. it('via where, where [lat, long] param', function(){
  264. var query = new Query();
  265. query.where('checkin').nearSphere([40, -72]);
  266. assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
  267. })
  268. it('via where, where lat and long params', function(){
  269. var query = new Query();
  270. query.where('checkin').nearSphere(40, -72);
  271. assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
  272. })
  273. it('not via where, where [lat, long] param', function(){
  274. var query = new Query();
  275. query.nearSphere('checkin', [40, -72]);
  276. assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
  277. })
  278. it('not via where, where lat and long params', function(){
  279. var query = new Query();
  280. query.nearSphere('checkin', 40, -72);
  281. assert.deepEqual(query._conditions, {checkin: {$nearSphere: [40, -72]}});
  282. })
  283. })
  284. describe('maxDistance', function(){
  285. it('via where', function(){
  286. var query = new Query();
  287. query.where('checkin').near([40, -72]).maxDistance(1);
  288. assert.deepEqual(query._conditions, {checkin: {$near: [40, -72], $maxDistance: 1}});
  289. })
  290. })
  291. describe('within', function(){
  292. describe('box', function(){
  293. it('not via where', function(){
  294. var query = new Query();
  295. query.within.box('gps', {ll: [5, 25], ur: [10, 30]});
  296. assert.deepEqual(query._conditions, {gps: {$within: {$box: [[5, 25], [10, 30]]}}});
  297. })
  298. it('via where', function(){
  299. var query = new Query();
  300. query.where('gps').within.box({ll: [5, 25], ur: [10, 30]});
  301. assert.deepEqual(query._conditions, {gps: {$within: {$box: [[5, 25], [10, 30]]}}});
  302. })
  303. })
  304. describe('center', function(){
  305. it('not via where', function(){
  306. var query = new Query();
  307. query.within.center('gps', {center: [5, 25], radius: 5});
  308. assert.deepEqual(query._conditions, {gps: {$within: {$center: [[5, 25], 5]}}});
  309. })
  310. it('via where', function(){
  311. var query = new Query();
  312. query.where('gps').within.center({center: [5, 25], radius: 5});
  313. assert.deepEqual(query._conditions, {gps: {$within: {$center: [[5, 25], 5]}}});
  314. })
  315. })
  316. describe('centerSphere', function(){
  317. it('not via where', function(){
  318. var query = new Query();
  319. query.within.centerSphere('gps', {center: [5, 25], radius: 5});
  320. assert.deepEqual(query._conditions, {gps: {$within: {$centerSphere: [[5, 25], 5]}}});
  321. })
  322. it('via where', function(){
  323. var query = new Query();
  324. query.where('gps').within.centerSphere({center: [5, 25], radius: 5});
  325. assert.deepEqual(query._conditions, {gps: {$within: {$centerSphere: [[5, 25], 5]}}});
  326. })
  327. })
  328. describe('polygon', function(){
  329. it('not via where', function(){
  330. var query = new Query();
  331. query.within.polygon('gps', [[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]);
  332. assert.deepEqual(query._conditions, {gps: {$within: {$polygon:[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]] }}});
  333. })
  334. it('via where', function(){
  335. var query = new Query();
  336. query.where('gps').within.polygon({ a: { x: 10, y: 20 }, b: { x: 15, y: 25 }, c: { x: 20, y: 20 }});
  337. assert.deepEqual(query._conditions, {gps: {$within: {$polygon: { a: { x: 10, y: 20 }, b: { x: 15, y: 25 }, c: { x: 20, y: 20 }} }}});
  338. })
  339. })
  340. })
  341. describe('exists', function(){
  342. it('0 args via where', function(){
  343. var query = new Query();
  344. query.where("username").exists();
  345. assert.deepEqual(query._conditions, {username: {$exists: true}});
  346. })
  347. it('1 arg via where', function(){
  348. var query = new Query();
  349. query.where("username").exists(false);
  350. assert.deepEqual(query._conditions, {username: {$exists: false}});
  351. })
  352. it('where 1 argument not via where', function(){
  353. var query = new Query();
  354. query.exists('username');
  355. assert.deepEqual(query._conditions, {username: {$exists: true}});
  356. })
  357. it('where 2 args not via where', function(){
  358. var query = new Query();
  359. query.exists("username", false);
  360. assert.deepEqual(query._conditions, {username: {$exists: false}});
  361. })
  362. })
  363. describe('all', function(){
  364. it('via where', function(){
  365. var query = new Query();
  366. query.where('pets').all(['dog', 'cat', 'ferret']);
  367. assert.deepEqual(query._conditions, {pets: {$all: ['dog', 'cat', 'ferret']}});
  368. })
  369. it('not via where', function(){
  370. var query = new Query();
  371. query.all('pets', ['dog', 'cat', 'ferret']);
  372. assert.deepEqual(query._conditions, {pets: {$all: ['dog', 'cat', 'ferret']}});
  373. })
  374. })
  375. describe('find', function(){
  376. it('strict array equivalence condition v', function(){
  377. var query = new Query();
  378. query.find({'pets': ['dog', 'cat', 'ferret']});
  379. assert.deepEqual(query._conditions, {pets: ['dog', 'cat', 'ferret']});
  380. })
  381. it('with no args', function(){
  382. var threw = false;
  383. var q = new Query();
  384. try {
  385. q.find();
  386. } catch (err) {
  387. threw = true;
  388. }
  389. assert.ok(!threw);
  390. })
  391. })
  392. describe('size', function(){
  393. it('via where', function(){
  394. var query = new Query();
  395. query.where('collection').size(5);
  396. assert.deepEqual(query._conditions, {collection: {$size: 5}});
  397. })
  398. it('not via where', function(){
  399. var query = new Query();
  400. query.size('collection', 5);
  401. assert.deepEqual(query._conditions, {collection: {$size: 5}});
  402. })
  403. })
  404. describe('slice', function(){
  405. it('where and positive limit param', function(){
  406. var query = new Query();
  407. query.where('collection').slice(5);
  408. assert.deepEqual(query._fields, {collection: {$slice: 5}});
  409. })
  410. it('where just negative limit param', function(){
  411. var query = new Query();
  412. query.where('collection').slice(-5);
  413. assert.deepEqual(query._fields, {collection: {$slice: -5}});
  414. })
  415. it('where [skip, limit] param', function () {
  416. var query = new Query();
  417. query.where('collection').slice([14, 10]); // Return the 15th through 25th
  418. assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
  419. })
  420. it('where skip and limit params', function(){
  421. var query = new Query();
  422. query.where('collection').slice(14, 10); // Return the 15th through 25th
  423. assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
  424. })
  425. it('where just positive limit param', function(){
  426. var query = new Query();
  427. query.where('collection').slice(5);
  428. assert.deepEqual(query._fields, {collection: {$slice: 5}});
  429. })
  430. it('where just negative limit param', function(){
  431. var query = new Query();
  432. query.where('collection').slice(-5);
  433. assert.deepEqual(query._fields, {collection: {$slice: -5}});
  434. })
  435. it('where the [skip, limit] param', function(){
  436. var query = new Query();
  437. query.where('collection').slice([14, 10]); // Return the 15th through 25th
  438. assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
  439. })
  440. it('where the skip and limit params', function(){
  441. var query = new Query();
  442. query.where('collection').slice(14, 10); // Return the 15th through 25th
  443. assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
  444. })
  445. it('not via where, with just positive limit param', function(){
  446. var query = new Query();
  447. query.slice('collection', 5);
  448. assert.deepEqual(query._fields, {collection: {$slice: 5}});
  449. })
  450. it('not via where, where just negative limit param', function(){
  451. var query = new Query();
  452. query.slice('collection', -5);
  453. assert.deepEqual(query._fields, {collection: {$slice: -5}});
  454. })
  455. it('not via where, where [skip, limit] param', function(){
  456. var query = new Query();
  457. query.slice('collection', [14, 10]); // Return the 15th through 25th
  458. assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
  459. })
  460. it('not via where, where skip and limit params', function(){
  461. var query = new Query();
  462. query.slice('collection', 14, 10); // Return the 15th through 25th
  463. assert.deepEqual(query._fields, {collection: {$slice: [14, 10]}});
  464. })
  465. })
  466. describe('elemMatch', function(){
  467. describe('not via where', function(){
  468. it('works', function(){
  469. var query = new Query();
  470. query.elemMatch('comments', {author: 'bnoguchi', votes: {$gte: 5}});
  471. assert.deepEqual(query._conditions, {comments: {$elemMatch: {author: 'bnoguchi', votes: {$gte: 5}}}});
  472. })
  473. it('where block notation', function(){
  474. var query = new Query();
  475. query.elemMatch('comments', function (elem) {
  476. elem.where('author', 'bnoguchi')
  477. elem.where('votes').gte(5);
  478. });
  479. assert.deepEqual(query._conditions, {comments: {$elemMatch: {author: 'bnoguchi', votes: {$gte: 5}}}});
  480. })
  481. })
  482. describe('via where', function(){
  483. it('works', function(){
  484. var query = new Query();
  485. query.where('comments').elemMatch({author: 'bnoguchi', votes: {$gte: 5}});
  486. assert.deepEqual(query._conditions, {comments: {$elemMatch: {author: 'bnoguchi', votes: {$gte: 5}}}});
  487. })
  488. it('where block notation', function(){
  489. var query = new Query();
  490. query.where('comments').elemMatch(function (elem) {
  491. elem.where('author', 'bnoguchi')
  492. elem.where('votes').gte(5);
  493. });
  494. assert.deepEqual(query._conditions, {comments: {$elemMatch: {author: 'bnoguchi', votes: {$gte: 5}}}});
  495. })
  496. })
  497. })
  498. describe('$where', function(){
  499. it('function arg', function(){
  500. var query = new Query();
  501. function filter () {
  502. return this.lastName === this.firstName;
  503. }
  504. query.$where(filter);
  505. assert.deepEqual(query._conditions, {$where: filter});
  506. })
  507. it('string arg', function(){
  508. var query = new Query();
  509. query.$where('this.lastName === this.firstName');
  510. assert.deepEqual(query._conditions, {$where: 'this.lastName === this.firstName'});
  511. })
  512. })
  513. describe('limit', function(){
  514. it('works', function(){
  515. var query = new Query();
  516. query.limit(5);
  517. assert.equal(query.options.limit,5);
  518. })
  519. })
  520. describe('skip', function(){
  521. it('works', function(){
  522. var query = new Query();
  523. query.skip(9);
  524. assert.equal(query.options.skip,9);
  525. })
  526. })
  527. describe('sort', function(){
  528. it('works', function(){
  529. var query = new Query();
  530. query.sort('a -c b');
  531. assert.deepEqual(query.options.sort, [['a', 1], ['c', -1], ['b', 1]]);
  532. query = new Query();
  533. query.sort({'a': 1, 'c': -1, 'b': 'asc', e: 'descending', f: 'ascending'});
  534. assert.deepEqual(query.options.sort, [['a', 1], ['c', -1], ['b', 'asc'], ['e', 'descending'], ['f', 'ascending']]);
  535. query = new Query();
  536. var e;
  537. try {
  538. query.sort(['a', 1]);
  539. } catch (err) {
  540. e= err;
  541. }
  542. assert.ok(e, 'uh oh. no error was thrown');
  543. assert.equal(e.message, 'Invalid sort() argument. Must be a string or object.');
  544. e= undefined;
  545. try {
  546. query.sort('a', 1, 'c', -1, 'b', 1);
  547. } catch (err) {
  548. e= err;
  549. }
  550. assert.ok(e, 'uh oh. no error was thrown');
  551. assert.equal(e.message, 'Invalid sort() argument. Must be a string or object.');
  552. })
  553. })
  554. describe('or', function(){
  555. it('works', function(){
  556. var query = new Query;
  557. query.find({ $or: [{x:1},{x:2}] });
  558. assert.equal(query._conditions.$or.length, 2);
  559. query.or([{y:"We're under attack"}, {z:47}]);
  560. assert.equal(query._conditions.$or.length, 4);
  561. assert.equal(query._conditions.$or[3].z, 47);
  562. query.or({z:"phew"});
  563. assert.equal(query._conditions.$or.length, 5);
  564. assert.equal(query._conditions.$or[3].z, 47);
  565. assert.equal(query._conditions.$or[4].z, "phew");
  566. });
  567. })
  568. describe('an empty query', function(){
  569. it('should not throw', function(){
  570. var query = new Query();
  571. var threw = false;
  572. try {
  573. query.exec();
  574. } catch (err) {
  575. threw = true;
  576. }
  577. assert.equal(threw, false);
  578. })
  579. });
  580. describe('casting', function(){
  581. it('to an array of mixed', function(){
  582. var query = new Query();
  583. var db = start();
  584. var Product = db.model('Product');
  585. db.close();
  586. var params = { _id: new DocumentObjectId, tags: { $in: [ 4, 8, 15, 16 ] }};
  587. query.cast(Product, params);
  588. assert.deepEqual(params.tags.$in, [4,8,15,16]);
  589. })
  590. it('find $ne should not cast single value to array for schematype of Array', function(){
  591. var query = new Query();
  592. var db = start();
  593. var Product = db.model('Product');
  594. var Comment = db.model('Comment');
  595. db.close();
  596. var id = new DocumentObjectId;
  597. var castedComment = { _id: id, text: 'hello there' };
  598. var comment = new Comment(castedComment);
  599. var params = {
  600. array: { $ne: 5 }
  601. , ids: { $ne: id }
  602. , comments: { $ne: comment }
  603. , strings: { $ne: 'Hi there' }
  604. , numbers: { $ne: 10000 }
  605. };
  606. query.cast(Product, params);
  607. assert.equal(params.array.$ne,5);
  608. assert.equal(params.ids.$ne, id);
  609. params.comments.$ne._id.toHexString();
  610. assert.deepEqual(params.comments.$ne, castedComment);
  611. assert.equal(params.strings.$ne, 'Hi there');
  612. assert.equal(params.numbers.$ne, 10000);
  613. params.array.$ne = [5];
  614. params.ids.$ne = [id];
  615. params.comments.$ne = [comment];
  616. params.strings.$ne = ['Hi there'];
  617. params.numbers.$ne = [10000];
  618. query.cast(Product, params);
  619. assert.ok(params.array.$ne instanceof Array);
  620. assert.equal(params.array.$ne[0], 5);
  621. assert.ok(params.ids.$ne instanceof Array);
  622. assert.equal(params.ids.$ne[0].toString(), id.toString());
  623. assert.ok(params.comments.$ne instanceof Array);
  624. assert.deepEqual(params.comments.$ne[0], castedComment);
  625. assert.ok(params.strings.$ne instanceof Array);
  626. assert.equal(params.strings.$ne[0], 'Hi there');
  627. assert.ok(params.numbers.$ne instanceof Array);
  628. assert.equal(params.numbers.$ne[0], 10000);
  629. })
  630. it('subdocument array with $ne: null should not throw', function(){
  631. var query = new Query();
  632. var db = start();
  633. var Product = db.model('Product');
  634. var Comment = db.model('Comment');
  635. db.close();
  636. var params = {
  637. comments: { $ne: null }
  638. };
  639. query.cast(Product, params);
  640. assert.strictEqual(params.comments.$ne, null);
  641. })
  642. it('find should not cast single value to array for schematype of Array', function(){
  643. var query = new Query();
  644. var db = start();
  645. var Product = db.model('Product');
  646. var Comment = db.model('Comment');
  647. db.close();
  648. var id = new DocumentObjectId;
  649. var castedComment = { _id: id, text: 'hello there' };
  650. var comment = new Comment(castedComment);
  651. var params = {
  652. array: 5
  653. , ids: id
  654. , comments: comment
  655. , strings: 'Hi there'
  656. , numbers: 10000
  657. };
  658. query.cast(Product, params);
  659. assert.equal(params.array,5);
  660. assert.equal(params.ids, id);
  661. params.comments._id.toHexString();
  662. assert.deepEqual(params.comments, castedComment);
  663. assert.equal(params.strings, 'Hi there');
  664. assert.equal(params.numbers, 10000);
  665. params.array = [5];
  666. params.ids = [id];
  667. params.comments = [comment];
  668. params.strings = ['Hi there'];
  669. params.numbers = [10000];
  670. query.cast(Product, params);
  671. assert.ok(params.array instanceof Array);
  672. assert.equal(params.array[0], 5);
  673. assert.ok(params.ids instanceof Array);
  674. assert.equal(params.ids[0].toString(), id.toString());
  675. assert.ok(params.comments instanceof Array);
  676. assert.deepEqual(params.comments[0], castedComment);
  677. assert.ok(params.strings instanceof Array);
  678. assert.equal(params.strings[0], 'Hi there');
  679. assert.ok(params.numbers instanceof Array);
  680. assert.equal(params.numbers[0], 10000);
  681. })
  682. it('an $elemMatch with $in works (gh-1100)', function(){
  683. var query = new Query();
  684. var db = start();
  685. var Product = db.model('Product');
  686. db.close();
  687. var ids = [String(new DocumentObjectId), String(new DocumentObjectId)];
  688. var params = { ids: { $elemMatch: { $in: ids }}};
  689. query.cast(Product, params);
  690. assert.ok(params.ids.$elemMatch.$in[0] instanceof DocumentObjectId);
  691. assert.ok(params.ids.$elemMatch.$in[1] instanceof DocumentObjectId);
  692. assert.deepEqual(params.ids.$elemMatch.$in[0].toString(), ids[0]);
  693. assert.deepEqual(params.ids.$elemMatch.$in[1].toString(), ids[1]);
  694. })
  695. it('inequality operators for an array', function() {
  696. var query = new Query();
  697. var db = start();
  698. var Product = db.model('Product');
  699. var Comment = db.model('Comment');
  700. db.close();
  701. var id = new DocumentObjectId;
  702. var castedComment = { _id: id, text: 'hello there' };
  703. var comment = new Comment(castedComment);
  704. var params = {
  705. ids: { $gt: id }
  706. , comments: { $gt: comment }
  707. , strings: { $gt: 'Hi there' }
  708. , numbers: { $gt: 10000 }
  709. };
  710. query.cast(Product, params);
  711. assert.equal(params.ids.$gt, id);
  712. assert.deepEqual(params.comments.$gt, castedComment);
  713. assert.equal(params.strings.$gt, 'Hi there');
  714. assert.equal(params.numbers.$gt, 10000);
  715. })
  716. })
  717. describe('distinct', function(){
  718. it('op', function(){
  719. var db = start();
  720. var query = new Query();
  721. var Product = db.model('Product');
  722. var q = new Query().bind(Product, 'distinct').distinct('blah', function(){
  723. db.close();
  724. })
  725. assert.equal(q.op,'distinct');
  726. })
  727. })
  728. describe('without a callback', function(){
  729. it('count, update, remove works', function(done){
  730. var db = start();
  731. var query = new Query();
  732. var Product = db.model('Product', 'update_products_' + random());
  733. new Query().bind(Product, 'count').count();
  734. Product.create({ tags: 12345 }, function (err) {
  735. assert.ifError(err);
  736. var time = 20;
  737. Product.find({ tags: 12345 }).update({ $set: { tags: 123456 }});
  738. setTimeout(function(){
  739. Product.find({ tags: 123456 }, function (err, p) {
  740. assert.ifError(err);
  741. assert.equal(1, p.length);
  742. Product.find({ tags: 123456 }).remove();
  743. setTimeout(function(){
  744. Product.find({ tags: 123456 }, function (err, p) {
  745. assert.ifError(err);
  746. assert.equal(0, p.length);
  747. db.close();
  748. done();
  749. });
  750. }, time);
  751. });
  752. }, time);
  753. });
  754. })
  755. });
  756. describe('findOne', function(){
  757. it('sets the op', function(){
  758. var db = start();
  759. var query = new Query();
  760. var Product = db.model('Product');
  761. var q = new Query().bind(Product, 'distinct');
  762. assert.equal(q.op,'distinct');
  763. q.findOne();
  764. assert.equal(q.op,'findOne');
  765. db.close();
  766. });
  767. });
  768. describe('querying/updating with model instance containing embedded docs should work (#454)', function(){
  769. it('works', function(done){
  770. var db = start();
  771. var Product = db.model('Product');
  772. var proddoc = { comments: [{ text: 'hello' }] };
  773. var prod2doc = { comments: [{ text: 'goodbye' }] };
  774. var prod = new Product(proddoc);
  775. var prod2 = new Product(prod2doc);
  776. prod.save(function (err) {
  777. assert.ifError(err);
  778. Product.findOne(prod, function (err, product) {
  779. assert.ifError(err);
  780. assert.equal(product.comments.length, 1);
  781. assert.equal(product.comments[0].text, 'hello');
  782. Product.update(product, prod2doc, function (err) {
  783. assert.ifError(err);
  784. Product.collection.findOne({ _id: product._id }, function (err, doc) {
  785. db.close();
  786. assert.ifError(err);
  787. assert.equal(doc.comments.length, 1);
  788. // ensure hidden private props were not saved to db
  789. assert.ok(!doc.comments[0].hasOwnProperty('parentArry') );
  790. assert.equal(doc.comments[0].text,'goodbye');
  791. done();
  792. });
  793. });
  794. });
  795. });
  796. })
  797. })
  798. describe('optionsForExecute', function(){
  799. it('should retain key order', function(){
  800. // this is important for query hints
  801. var hint = { x: 1, y: 1, z: 1 };
  802. var a = JSON.stringify({ hint: hint, safe: true});
  803. var q = new Query;
  804. q.hint(hint);
  805. var options = q._optionsForExec({ schema: { options: { safe: true } }});
  806. assert.equal(a,JSON.stringify(options));
  807. })
  808. })
  809. // Advanced Query options
  810. describe('options', function(){
  811. describe('maxscan', function(){
  812. it('works', function(){
  813. var query = new Query();
  814. query.maxscan(100);
  815. assert.equal(query.options.maxscan,100);
  816. });
  817. })
  818. describe('slaveOk', function(){
  819. var query = new Query();
  820. query.slaveOk();
  821. assert.equal(true, query.options.slaveOk);
  822. var query = new Query();
  823. query.slaveOk(true);
  824. assert.equal(true, query.options.slaveOk);
  825. var query = new Query();
  826. query.slaveOk(false);
  827. assert.equal(false, query.options.slaveOk);
  828. })
  829. describe('tailable', function(){
  830. it('works', function(){
  831. var query = new Query();
  832. query.tailable();
  833. assert.equal(true, query.options.tailable);
  834. var query = new Query();
  835. query.tailable(true);
  836. assert.equal(true, query.options.tailable);
  837. var query = new Query();
  838. query.tailable(false);
  839. assert.equal(false, query.options.tailable);
  840. })
  841. });
  842. describe('comment', function(){
  843. it('works', function(){
  844. var query = new Query;
  845. assert.equal('function',typeof query.comment);
  846. assert.equal(query.comment('Lowpass is more fun'),query);
  847. assert.equal(query.options.comment,'Lowpass is more fun');
  848. });
  849. })
  850. describe('hint', function(){
  851. it('works', function(){
  852. var query2 = new Query();
  853. query2.hint({'indexAttributeA': 1, 'indexAttributeB': -1});
  854. assert.deepEqual(query2.options.hint, {'indexAttributeA': 1, 'indexAttributeB': -1});
  855. assert.throws(function(){
  856. var query3 = new Query();
  857. query3.hint('indexAttributeA');
  858. }, /Invalid hint./);
  859. })
  860. })
  861. describe('snapshot', function(){
  862. it('works', function(){
  863. var query = new Query();
  864. query.snapshot(true);
  865. assert.equal(true, query.options.snapshot);
  866. });
  867. })
  868. describe('batchSize', function(){
  869. it('works', function(){
  870. var query = new Query();
  871. query.batchSize(10);
  872. assert.equal(query.options.batchSize,10);
  873. });
  874. })
  875. describe('read', function(){
  876. var P = mongoose.mongo.ReadPreference;
  877. describe('without tags', function(){
  878. it('works', function(){
  879. var query = new Query();
  880. query.read('primary');
  881. assert.ok(query.options.readPreference instanceof P);
  882. assert.equal(query.options.readPreference.mode, 'primary');
  883. query.read('p');
  884. assert.ok(query.options.readPreference instanceof P);
  885. assert.equal(query.options.readPreference.mode, 'primary');
  886. query.read('primaryPrefered');
  887. assert.ok(query.options.readPreference instanceof P);
  888. assert.equal(query.options.readPreference.mode, 'primaryPrefered');
  889. query.read('pp');
  890. assert.ok(query.options.readPreference instanceof P);
  891. assert.equal(query.options.readPreference.mode, 'primaryPrefered');
  892. query.read('secondary');
  893. assert.ok(query.options.readPreference instanceof P);
  894. assert.equal(query.options.readPreference.mode, 'secondary');
  895. query.read('s');
  896. assert.ok(query.options.readPreference instanceof P);
  897. assert.equal(query.options.readPreference.mode, 'secondary');
  898. query.read('secondaryPrefered');
  899. assert.ok(query.options.readPreference instanceof P);
  900. assert.equal(query.options.readPreference.mode, 'secondaryPrefered');
  901. query.read('sp');
  902. assert.ok(query.options.readPreference instanceof P);
  903. assert.equal(query.options.readPreference.mode, 'secondaryPrefered');
  904. query.read('nearest');
  905. assert.ok(query.options.readPreference instanceof P);
  906. assert.equal(query.options.readPreference.mode, 'nearest');
  907. query.read('n');
  908. assert.ok(query.options.readPreference instanceof P);
  909. assert.equal(query.options.readPreference.mode, 'nearest');
  910. });
  911. })
  912. describe('with tags', function(){
  913. it('works', function(){
  914. var query = new Query();
  915. var tags = [{ dc: 'sf', s: 1}, { dc: 'jp', s: 2 }]
  916. query.read('p', tags);
  917. assert.ok(query.options.readPreference instanceof P);
  918. assert.equal(query.options.readPreference.mode, 'primary');
  919. assert.ok(Array.isArray(query.options.readPreference.tags));
  920. assert.equal(query.options.readPreference.tags[0].dc, 'sf');
  921. assert.equal(query.options.readPreference.tags[0].s, 1);
  922. assert.equal(query.options.readPreference.tags[1].dc, 'jp');
  923. assert.equal(query.options.readPreference.tags[1].s, 2);
  924. });
  925. })
  926. describe('inherits its models schema read option', function(){
  927. var schema, M;
  928. before(function () {
  929. schema = new Schema({}, { read: 'p' });
  930. M = mongoose.model('schemaOptionReadPrefWithQuery', schema);
  931. })
  932. it('if not set in query', function(){
  933. var options = M.where()._optionsForExec(M);
  934. assert.ok(options.readPreference instanceof P);
  935. assert.equal(options.readPreference.mode, 'primary');
  936. })
  937. it('if set in query', function(){
  938. var options = M.where().read('s')._optionsForExec(M);
  939. assert.ok(options.readPreference instanceof P);
  940. assert.equal(options.readPreference.mode, 'secondary');
  941. })
  942. })
  943. })
  944. })
  945. describe('setOptions', function(){
  946. it('works', function(done){
  947. var q = new Query;
  948. q.setOptions({ thing: "cat" });
  949. q.setOptions({ populate: ['fans'] });
  950. q.setOptions({ batchSize: 10 });
  951. q.setOptions({ limit: 4 });
  952. q.setOptions({ skip: 3 });
  953. q.setOptions({ sort: '-blah' });
  954. q.setOptions({ sort: {'woot': -1} });
  955. q.setOptions({ hint: { index1: 1, index2: -1 }});
  956. q.setOptions({ read: ['s', [{dc:'eu'}]]});
  957. assert.equal(q.options.thing, 'cat');
  958. assert.deepEqual(q.options.populate.fans, { fields: undefined, conditions: undefined, options: undefined, model: undefined });
  959. assert.equal(q.options.batchSize, 10);
  960. assert.equal(q.options.limit, 4);
  961. assert.equal(q.options.skip, 3);
  962. assert.equal(q.options.sort.length, 2);
  963. assert.equal(q.options.sort[0][0], 'blah');
  964. assert.equal(q.options.sort[0][1], -1);
  965. assert.equal(q.options.sort[1][0], 'woot');
  966. assert.equal(q.options.sort[1][1], -1);
  967. assert.equal(q.options.hint.index1, 1);
  968. assert.equal(q.options.hint.index2, -1);
  969. assert.equal(q.options.readPreference.mode, 'secondary');
  970. assert.equal(q.options.readPreference.tags[0].dc, 'eu');
  971. var db = start();
  972. var Product = db.model('Product', 'Product_setOptions_test');
  973. Product.create(
  974. { numbers: [3,4,5] }
  975. , { strings: 'hi there'.split(' ') } , function (err, doc1, doc2) {
  976. assert.ifError(err);
  977. Product.find().setOptions({ limit: 1, sort: {_id: -1}, read: 'n' }).exec(function (err, docs) {
  978. db.close();
  979. assert.ifError(err);
  980. assert.equal(docs.length, 1);
  981. assert.equal(docs[0].id, doc2.id);
  982. done();
  983. });
  984. });
  985. })
  986. })
  987. describe('update', function(){
  988. it('when empty, nothing is run', function(){
  989. var q = new Query;
  990. assert.equal(false, !!q._castUpdate({}));
  991. })
  992. })
  993. })