command.test.ts 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. import * as assert from 'power-assert'
  2. import tcb from '../../../src/index'
  3. import * as Config from '../../config.local'
  4. import * as common from '../../common/index'
  5. const app = tcb.init(Config)
  6. const db = app.database()
  7. describe.skip('test/unit/collection.test.ts', () => {
  8. const collName = 'coll-1'
  9. const collection = db.collection(collName)
  10. const command = db.command
  11. const _ = command
  12. it('operator', async () => {
  13. let a
  14. a = _.gt(4)
  15. const result = await collection.where({ a }).update({ c: { d: _.mul(3) } })
  16. })
  17. })
  18. describe('stdDevPop', () => {
  19. let studentsCollection = null
  20. const collectionName = 'test-students'
  21. const data = [
  22. { group: 'a', score: 84 },
  23. { group: 'a', score: 96 },
  24. { group: 'b', score: 80 },
  25. { group: 'b', score: 100 }
  26. ]
  27. beforeAll(async () => {
  28. studentsCollection = await common.safeCollection(db, collectionName)
  29. const success = await studentsCollection.create(data)
  30. assert.strictEqual(success, true)
  31. })
  32. afterAll(async () => {
  33. const success = await studentsCollection.remove()
  34. assert.strictEqual(success, true)
  35. })
  36. it('计算不同组的标准差', async () => {
  37. const $ = db.command.aggregate
  38. const result = await db
  39. .collection(collectionName)
  40. .aggregate()
  41. .group({
  42. _id: '$group',
  43. stdDev: $.stdDevPop('$score')
  44. })
  45. .end()
  46. const stdDevs = {
  47. a: null,
  48. b: null
  49. }
  50. result.data.forEach(item => (stdDevs[item._id] = item.stdDev))
  51. // a分组标准差为: 6; b分组标准差为: 10
  52. assert.strictEqual(stdDevs.a, 6)
  53. assert.strictEqual(stdDevs.b, 10)
  54. })
  55. })
  56. describe('stdDevSamp', () => {
  57. let studentsCollection = null
  58. const collectionName = 'test-students'
  59. const data = [{ score: 80 }, { score: 100 }]
  60. beforeAll(async () => {
  61. studentsCollection = await common.safeCollection(db, collectionName)
  62. const success = await studentsCollection.create(data)
  63. assert.strictEqual(success, true)
  64. })
  65. afterAll(async () => {
  66. const success = await studentsCollection.remove()
  67. assert.strictEqual(success, true)
  68. })
  69. it('计算标准样本偏差', async () => {
  70. const $ = db.command.aggregate
  71. const result = await db
  72. .collection(collectionName)
  73. .aggregate()
  74. .group({
  75. _id: null,
  76. ageStdDev: $.stdDevSamp('$score')
  77. })
  78. .end()
  79. // data 的标准样本偏差为 14.14
  80. assert.strictEqual(result.data[0].ageStdDev.toFixed(2), '14.14')
  81. })
  82. })
  83. describe('sum', () => {
  84. let goodsCollection = null
  85. const $ = db.command.aggregate
  86. const collectionName = 'test-goods'
  87. const data = [
  88. { cost: -10, price: 100 },
  89. { cost: -15, price: 1 },
  90. { cost: -10, price: 10 }
  91. ]
  92. beforeAll(async () => {
  93. goodsCollection = await common.safeCollection(db, collectionName)
  94. const success = await goodsCollection.create(data)
  95. assert.strictEqual(success, true)
  96. })
  97. afterAll(async () => {
  98. const success = await goodsCollection.remove()
  99. assert.strictEqual(success, true)
  100. })
  101. it('参数为单独字段', async () => {
  102. const result = await db
  103. .collection(collectionName)
  104. .aggregate()
  105. .group({
  106. _id: null,
  107. totalPrice: $.sum('$price')
  108. })
  109. .end()
  110. assert.strictEqual(result.data[0].totalPrice, 111)
  111. })
  112. it('参数为字段列表', async () => {
  113. const result = await db
  114. .collection(collectionName)
  115. .aggregate()
  116. .group({
  117. _id: null,
  118. totalProfit: $.sum($.sum(['$price', '$cost']))
  119. })
  120. .end()
  121. assert.strictEqual(result.data[0].totalProfit, 76)
  122. })
  123. })
  124. describe('let', () => {
  125. let goodsCollection = null
  126. const $ = db.command.aggregate
  127. const collectionName = 'test-goods'
  128. const data = [
  129. { cost: -10, discount: 0.95, price: 100 },
  130. { cost: -15, discount: 0.98, price: 1 },
  131. { cost: -10, discount: 1, price: 10 }
  132. ]
  133. beforeAll(async () => {
  134. goodsCollection = await common.safeCollection(db, collectionName)
  135. const success = await goodsCollection.create(data)
  136. assert.strictEqual(success, true)
  137. })
  138. afterAll(async () => {
  139. const success = await goodsCollection.remove()
  140. assert.strictEqual(success, true)
  141. })
  142. it('参数为单独字段', async () => {
  143. const result = await db
  144. .collection(collectionName)
  145. .aggregate()
  146. .project({
  147. profit: $.let({
  148. vars: {
  149. priceTotal: $.multiply(['$price', '$discount'])
  150. },
  151. in: $.sum(['$$priceTotal', '$cost'])
  152. })
  153. })
  154. .end()
  155. assert.strictEqual(result.data.length, 3)
  156. })
  157. })
  158. describe('条件操作符', () => {
  159. let goodsCollection = null
  160. const $ = db.command.aggregate
  161. const collectionName = 'test-goods'
  162. const data = [
  163. { name: 'a', amount: 100, desc: 'A' },
  164. { name: 'b', amount: 200, desc: null },
  165. { name: 'c', amount: 300 }
  166. ]
  167. beforeAll(async () => {
  168. goodsCollection = await common.safeCollection(db, collectionName)
  169. const success = await goodsCollection.create(data)
  170. assert.strictEqual(success, true)
  171. })
  172. afterAll(async () => {
  173. const success = await goodsCollection.remove()
  174. assert.strictEqual(success, true)
  175. })
  176. it('cond', async () => {
  177. const $ = db.command.aggregate
  178. const result = await db
  179. .collection(collectionName)
  180. .aggregate()
  181. .project({
  182. _id: 0,
  183. name: 1,
  184. discount: $.cond({
  185. if: $.gte(['$amount', 200]),
  186. then: 0.7,
  187. else: 0.9
  188. })
  189. })
  190. .end()
  191. assert.deepStrictEqual(result.data, [
  192. { name: 'a', discount: 0.9 },
  193. { name: 'b', discount: 0.7 },
  194. { name: 'c', discount: 0.7 }
  195. ])
  196. })
  197. it('ifNull', async () => {
  198. const $ = db.command.aggregate
  199. const result = await db
  200. .collection(collectionName)
  201. .aggregate()
  202. .project({
  203. _id: 0,
  204. name: 1,
  205. desc: $.ifNull(['$desc', 'Not defined'])
  206. })
  207. .end()
  208. assert.deepStrictEqual(result.data, [
  209. { desc: 'A', name: 'a' },
  210. { desc: 'Not defined', name: 'b' },
  211. { desc: 'Not defined', name: 'c' }
  212. ])
  213. })
  214. it('switch', async () => {
  215. const $ = db.command.aggregate
  216. const result = await db
  217. .collection(collectionName)
  218. .aggregate()
  219. .project({
  220. _id: 0,
  221. name: 1,
  222. discount: $.switch({
  223. branches: [
  224. { case: $.gt(['$amount', 250]), then: 0.8 },
  225. { case: $.gt(['$amount', 150]), then: 0.9 }
  226. ],
  227. default: 1
  228. })
  229. })
  230. .end()
  231. assert.deepStrictEqual(result.data, [
  232. { name: 'a', discount: 1 },
  233. { name: 'b', discount: 0.9 },
  234. { name: 'c', discount: 0.8 }
  235. ])
  236. })
  237. })
  238. describe('group操作符', () => {
  239. let studentsCollection = null,
  240. passagesCollection = null
  241. const $ = db.command.aggregate
  242. const studentsName = 'test-students'
  243. const studentsData = [
  244. { group: 'a', name: 'stu1', score: 84 },
  245. { group: 'a', name: 'stu2', score: 96 },
  246. { group: 'b', name: 'stu3', score: 80 },
  247. { group: 'b', name: 'stu4', score: 100 }
  248. ]
  249. const passagesName = 'test-passages'
  250. const passagesData = [
  251. { category: 'web', tags: ['JavaScript', 'CSS'], title: 'title1' },
  252. { category: 'System', tags: ['C++', 'C'], title: 'title2' }
  253. ]
  254. beforeAll(async () => {
  255. studentsCollection = await common.safeCollection(db, studentsName)
  256. passagesCollection = await common.safeCollection(db, passagesName)
  257. assert.strictEqual(await studentsCollection.create(studentsData), true)
  258. assert.strictEqual(await passagesCollection.create(passagesData), true)
  259. })
  260. afterAll(async () => {
  261. assert.strictEqual(await studentsCollection.remove(), true)
  262. assert.strictEqual(await passagesCollection.remove(), true)
  263. })
  264. it('push', async () => {
  265. const result = await db
  266. .collection(studentsName)
  267. .aggregate()
  268. .group({
  269. _id: '$group',
  270. students: $.push({
  271. name: '$name',
  272. score: '$score'
  273. })
  274. })
  275. .end()
  276. const valid = result.data.every(item => 'students' in item)
  277. assert.strictEqual(valid, true)
  278. })
  279. it('max', async () => {
  280. const result = await db
  281. .collection(studentsName)
  282. .aggregate()
  283. .group({
  284. _id: '$group',
  285. maxScore: $.max('$score')
  286. })
  287. .end()
  288. assert.strictEqual(result.data.length, 2)
  289. })
  290. it('min', async () => {
  291. const result = await db
  292. .collection(studentsName)
  293. .aggregate()
  294. .group({
  295. _id: '$group',
  296. minScore: $.min('$score')
  297. })
  298. .end()
  299. assert.strictEqual(result.data.length, 2)
  300. })
  301. it('last', async () => {
  302. const result = await db
  303. .collection(studentsName)
  304. .aggregate()
  305. .sort({
  306. score: 1
  307. })
  308. .group({
  309. _id: null,
  310. max: $.last('$score')
  311. })
  312. .end()
  313. assert(result.data[0].max, 100)
  314. })
  315. it('first', async () => {
  316. const result = await db
  317. .collection(studentsName)
  318. .aggregate()
  319. .sort({
  320. score: 1
  321. })
  322. .group({
  323. _id: null,
  324. min: $.first('$score')
  325. })
  326. .end()
  327. assert(result.data[0].min, 80)
  328. })
  329. it('avg', async () => {
  330. const result = await db
  331. .collection(studentsName)
  332. .aggregate()
  333. .group({
  334. _id: null,
  335. average: $.avg('$score')
  336. })
  337. .end()
  338. assert(result.data[0].average, 90)
  339. })
  340. describe('addToSet', async () => {
  341. it('非数组字段', async () => {
  342. const result = await db
  343. .collection(passagesName)
  344. .aggregate()
  345. .group({
  346. _id: null,
  347. categories: $.addToSet('$category')
  348. })
  349. .end()
  350. assert(result.data[0].categories.length, 2)
  351. })
  352. it('数组字段', async () => {
  353. const result = await db
  354. .collection(passagesName)
  355. .aggregate()
  356. .group({
  357. _id: null,
  358. tagsList: $.addToSet('$tags')
  359. })
  360. .end()
  361. const valid = result.data.some(item => Array.isArray(item.tagsList))
  362. assert(valid, true)
  363. })
  364. })
  365. })
  366. describe('字面量操作符', () => {
  367. let goodsCollection = null
  368. const $ = db.command.aggregate
  369. const collectionName = 'test-goods'
  370. const data = [{ price: '$1' }, { price: '$2.50' }, { price: '$3.60' }, { price: '$4.60' }]
  371. beforeAll(async () => {
  372. goodsCollection = await common.safeCollection(db, collectionName)
  373. const success = await goodsCollection.create(data)
  374. assert.strictEqual(success, true)
  375. })
  376. afterAll(async () => {
  377. const success = await goodsCollection.remove()
  378. assert.strictEqual(success, true)
  379. })
  380. it('以字面量的形式使用$', async () => {
  381. const $ = db.command.aggregate
  382. const result = await db
  383. .collection(collectionName)
  384. .aggregate()
  385. .project({
  386. _id: 0,
  387. isOneDollar: $.eq(['$price', $.literal('$1')])
  388. })
  389. .end()
  390. assert.deepStrictEqual(result.data, [
  391. { isOneDollar: true },
  392. { isOneDollar: false },
  393. { isOneDollar: false },
  394. { isOneDollar: false }
  395. ])
  396. })
  397. it('投影一个字段,对应的值为1', async () => {
  398. const $ = db.command.aggregate
  399. const result = await db
  400. .collection(collectionName)
  401. .aggregate()
  402. .project({
  403. _id: 0,
  404. price: 1,
  405. amount: $.literal(1)
  406. })
  407. .end()
  408. assert.deepStrictEqual(result.data, [
  409. { amount: 1, price: '$1' },
  410. { amount: 1, price: '$2.50' },
  411. { amount: 1, price: '$3.60' },
  412. { amount: 1, price: '$4.60' }
  413. ])
  414. })
  415. })
  416. describe('字符串操作符', () => {
  417. let studentsCollection = null,
  418. personCollection = null
  419. const $ = db.command.aggregate
  420. const studentsName = 'test-students'
  421. const studentsData = [
  422. {
  423. birthday: '1999/12/12',
  424. date: new Date('1999/12/12'),
  425. firstName: 'Yuanxin',
  426. group: 'a',
  427. lastName: 'Dong',
  428. score: 84
  429. },
  430. {
  431. birthday: '1998/11/11',
  432. date: new Date('1998/11/11'),
  433. firstName: 'Weijia',
  434. group: 'a',
  435. lastName: 'Wang',
  436. score: 96
  437. },
  438. {
  439. birthday: '1997/10/10',
  440. date: new Date('1997/10/10'),
  441. firstName: 'Chengxi',
  442. group: 'b',
  443. lastName: 'Li',
  444. score: 80
  445. }
  446. ]
  447. const personName = 'test-person'
  448. const personData = [{ name: 'dongyuanxin', nickname: '心谭' }]
  449. beforeAll(async () => {
  450. studentsCollection = await common.safeCollection(db, studentsName)
  451. personCollection = await common.safeCollection(db, personName)
  452. assert.strictEqual(await studentsCollection.create(studentsData), true)
  453. assert.strictEqual(await personCollection.create(personData), true)
  454. })
  455. afterAll(async () => {
  456. assert.strictEqual(await studentsCollection.remove(), true)
  457. assert.strictEqual(await personCollection.remove(), true)
  458. })
  459. it('concat', async () => {
  460. const result = await db
  461. .collection(studentsName)
  462. .aggregate()
  463. .project({
  464. _id: 0,
  465. fullName: $.concat(['$firstName', ' ', '$lastName'])
  466. })
  467. .end()
  468. assert.deepStrictEqual(result.data, [
  469. { fullName: 'Yuanxin Dong' },
  470. { fullName: 'Weijia Wang' },
  471. { fullName: 'Chengxi Li' }
  472. ])
  473. })
  474. describe('dateToString', async () => {
  475. it('格式化日期', async () => {
  476. const result = await db
  477. .collection(studentsName)
  478. .aggregate()
  479. .project({
  480. _id: 0,
  481. formatDate: $.dateToString({
  482. date: '$date',
  483. format: '%Y-%m-%d'
  484. })
  485. })
  486. .end()
  487. assert.deepStrictEqual(result.data, [
  488. { formatDate: '1999-12-11' },
  489. { formatDate: '1998-11-10' },
  490. { formatDate: '1997-10-09' }
  491. ])
  492. })
  493. it('时区时间', async () => {
  494. const result = await db
  495. .collection(studentsName)
  496. .aggregate()
  497. .project({
  498. _id: 0,
  499. formatDate: $.dateToString({
  500. date: '$date',
  501. format: '%H:%M:%S',
  502. timezone: 'Asia/Shanghai'
  503. })
  504. })
  505. .end()
  506. const valid = result.data.every(item => item.formatDate === '00:00:00')
  507. assert.ok(valid)
  508. })
  509. it('缺失情况的默认值', async () => {
  510. const result = await db
  511. .collection(studentsName)
  512. .aggregate()
  513. .project({
  514. _id: 0,
  515. formatDate: $.dateToString({
  516. date: '$empty',
  517. onNull: 'null'
  518. })
  519. })
  520. .end()
  521. const valid = result.data.every(item => item.formatDate === 'null')
  522. assert.ok(valid)
  523. })
  524. })
  525. it('indexOfBytes', async () => {
  526. const result = await db
  527. .collection(studentsName)
  528. .aggregate()
  529. .project({
  530. _id: 0,
  531. aStrIndex: $.indexOfBytes(['$firstName', 'a'])
  532. })
  533. .end()
  534. assert.deepStrictEqual(result.data, [{ aStrIndex: 2 }, { aStrIndex: 5 }, { aStrIndex: -1 }])
  535. })
  536. it('indexOfCP', async () => {
  537. const result = await db
  538. .collection(studentsName)
  539. .aggregate()
  540. .project({
  541. _id: 0,
  542. aStrIndex: $.indexOfCP(['$firstName', 'a'])
  543. })
  544. .end()
  545. assert.deepStrictEqual(result.data, [{ aStrIndex: 2 }, { aStrIndex: 5 }, { aStrIndex: -1 }])
  546. })
  547. it('split', async () => {
  548. const result = await db
  549. .collection(studentsName)
  550. .aggregate()
  551. .project({
  552. _id: 0,
  553. birthday: $.split(['$birthday', '/'])
  554. })
  555. .end()
  556. assert.deepStrictEqual(result.data, [
  557. { birthday: ['1999', '12', '12'] },
  558. { birthday: ['1998', '11', '11'] },
  559. { birthday: ['1997', '10', '10'] }
  560. ])
  561. })
  562. it('strcasecmp', async () => {
  563. const result = await db
  564. .collection(studentsName)
  565. .aggregate()
  566. .project({
  567. _id: 0,
  568. result: $.strcasecmp(['$firstName', '$lastName'])
  569. })
  570. .end()
  571. assert.deepStrictEqual(result.data, [{ result: 1 }, { result: 1 }, { result: -1 }])
  572. })
  573. it.skip('strLenBytes', async () => {
  574. const result = await db
  575. .collection(personName)
  576. .aggregate()
  577. .project({
  578. _id: 0,
  579. nameLength: $.strLenBytes('$name'),
  580. nicknameLength: $.strLenBytes('$nickname')
  581. })
  582. .end()
  583. assert.deepStrictEqual(result.data, [{ nameLength: 11, nicknameLength: 6 }])
  584. })
  585. it.skip('strLenCP', async () => {
  586. const result = await db
  587. .collection(personName)
  588. .aggregate()
  589. .project({
  590. _id: 0,
  591. nameLength: $.strLenCP('$name'),
  592. nicknameLength: $.strLenCP('$nickname')
  593. })
  594. .end()
  595. assert.deepStrictEqual(result.data, [{ nameLength: 11, nicknameLength: 2 }])
  596. })
  597. it('substr', async () => {
  598. const result = await db
  599. .collection(studentsName)
  600. .aggregate()
  601. .project({
  602. _id: 0,
  603. year: $.substr(['$birthday', 0, 4]),
  604. month: $.substr(['$birthday', 5, 2]),
  605. day: $.substr(['$birthday', 8, -1])
  606. })
  607. .end()
  608. assert.deepStrictEqual(result.data, [
  609. { day: '12', month: '12', year: '1999' },
  610. { day: '11', month: '11', year: '1998' },
  611. { day: '10', month: '10', year: '1997' }
  612. ])
  613. })
  614. it('substrBytes', async () => {
  615. const result = await db
  616. .collection(studentsName)
  617. .aggregate()
  618. .project({
  619. _id: 0,
  620. year: $.substrBytes(['$birthday', 0, 4]),
  621. month: $.substrBytes(['$birthday', 5, 2]),
  622. day: $.substrBytes(['$birthday', 8, -1])
  623. })
  624. .end()
  625. assert.deepStrictEqual(result.data, [
  626. { day: '12', month: '12', year: '1999' },
  627. { day: '11', month: '11', year: '1998' },
  628. { day: '10', month: '10', year: '1997' }
  629. ])
  630. })
  631. test.skip('substrCP', async () => {
  632. const result = await db
  633. .collection(personName)
  634. .aggregate()
  635. .project({
  636. _id: 0,
  637. firstCh: $.substrCP(['$nickname', 0, 1])
  638. })
  639. .end()
  640. assert.deepStrictEqual(result.data, [{ firstCh: '心' }])
  641. })
  642. test('toLower', async () => {
  643. const result = await db
  644. .collection(studentsName)
  645. .aggregate()
  646. .project({
  647. _id: 0,
  648. result: $.toLower('$firstName')
  649. })
  650. .end()
  651. assert.deepStrictEqual(result.data, [
  652. { result: 'yuanxin' },
  653. { result: 'weijia' },
  654. { result: 'chengxi' }
  655. ])
  656. })
  657. test('toUpper', async () => {
  658. const result = await db
  659. .collection(studentsName)
  660. .aggregate()
  661. .project({
  662. _id: 0,
  663. result: $.toUpper('$lastName')
  664. })
  665. .end()
  666. assert.deepStrictEqual(result.data, [
  667. { result: 'DONG' },
  668. { result: 'WANG' },
  669. { result: 'LI' }
  670. ])
  671. })
  672. })
  673. describe('mergeObjects', () => {
  674. let goodsCollection = null
  675. const $ = db.command.aggregate
  676. const collectionName = 'test-goods'
  677. const data = [
  678. { name: 'A', foo: { a: 1 }, bar: { b: 2 } },
  679. { name: 'A', foo: { c: 1 }, bar: { d: 2 } },
  680. { name: 'A', foo: { e: 1 }, bar: { f: 2 } }
  681. ]
  682. beforeAll(async () => {
  683. goodsCollection = await common.safeCollection(db, collectionName)
  684. const success = await goodsCollection.create(data)
  685. assert.strictEqual(success, true)
  686. })
  687. afterAll(async () => {
  688. const success = await goodsCollection.remove()
  689. assert.strictEqual(success, true)
  690. })
  691. it('在group中使用', async () => {
  692. const $ = db.command.aggregate
  693. const result = await db
  694. .collection(collectionName)
  695. .aggregate()
  696. .group({
  697. _id: '$name',
  698. mergedFoo: $.mergeObjects('$foo'),
  699. mergeBar: $.mergeObjects('$bar')
  700. })
  701. .end()
  702. assert.deepStrictEqual(result.data, [
  703. {
  704. _id: 'A',
  705. mergedFoo: { a: 1, c: 1, e: 1 },
  706. mergeBar: { b: 2, d: 2, f: 2 }
  707. }
  708. ])
  709. })
  710. it('在group以外使用', async () => {
  711. const $ = db.command.aggregate
  712. const result = await db
  713. .collection(collectionName)
  714. .aggregate()
  715. .project({
  716. _id: 0,
  717. foobar: $.mergeObjects(['$foo', '$bar'])
  718. })
  719. .end()
  720. assert.deepStrictEqual(result.data, [
  721. { foobar: { a: 1, b: 2 } },
  722. { foobar: { c: 1, d: 2 } },
  723. { foobar: { e: 1, f: 2 } }
  724. ])
  725. })
  726. })
  727. describe('集合操作', () => {
  728. let goodsCollection = null
  729. const $ = db.command.aggregate
  730. const collectionName = 'test-goods'
  731. const data = [
  732. { arr: [true] },
  733. { arr: [] },
  734. { arr: [true, false] },
  735. { arr: [1] },
  736. { arr: [1, 0] },
  737. { arr: ['stark'] }
  738. ]
  739. beforeAll(async () => {
  740. goodsCollection = await common.safeCollection(db, collectionName)
  741. const success = await goodsCollection.create(data)
  742. assert.strictEqual(success, true)
  743. })
  744. afterAll(async () => {
  745. const success = await goodsCollection.remove()
  746. assert.strictEqual(success, true)
  747. })
  748. it('allElementsTrue', async () => {
  749. const $ = db.command.aggregate
  750. const result = await db
  751. .collection(collectionName)
  752. .aggregate()
  753. .project({
  754. _id: 0,
  755. allElementsTrue: $.allElementsTrue(['$arr'])
  756. })
  757. .end()
  758. assert.deepStrictEqual(result.data, [
  759. { allElementsTrue: true },
  760. { allElementsTrue: true },
  761. { allElementsTrue: false },
  762. { allElementsTrue: true },
  763. { allElementsTrue: false },
  764. { allElementsTrue: true }
  765. ])
  766. })
  767. it('anyElementTrue', async () => {
  768. const $ = db.command.aggregate
  769. const result = await db
  770. .collection(collectionName)
  771. .aggregate()
  772. .project({
  773. _id: 0,
  774. anyElementTrue: $.anyElementTrue(['$arr'])
  775. })
  776. .end()
  777. assert.deepStrictEqual(result.data, [
  778. { anyElementTrue: true },
  779. { anyElementTrue: false },
  780. { anyElementTrue: true },
  781. { anyElementTrue: true },
  782. { anyElementTrue: true },
  783. { anyElementTrue: true }
  784. ])
  785. })
  786. })
  787. describe('集合操作2', () => {
  788. let goodsCollection = null
  789. const $ = db.command.aggregate
  790. const collectionName = 'test-goods'
  791. const data = [
  792. { A: [1, 2], B: [1, 2] },
  793. { A: [1, 2], B: [2, 1, 2] },
  794. { A: [1, 2], B: [1, 2, 3] },
  795. { A: [1, 2], B: [3, 1] },
  796. { A: [1, 2], B: [] },
  797. { A: [1, 2], B: [{}, []] },
  798. { A: [], B: [] },
  799. { A: [], B: [1] }
  800. ]
  801. beforeAll(async () => {
  802. goodsCollection = await common.safeCollection(db, collectionName)
  803. const success = await goodsCollection.create(data)
  804. assert.strictEqual(success, true)
  805. })
  806. afterAll(async () => {
  807. const success = await goodsCollection.remove()
  808. assert.strictEqual(success, true)
  809. })
  810. it('setDifference', async () => {
  811. const result = await db
  812. .collection(collectionName)
  813. .aggregate()
  814. .project({
  815. _id: 0,
  816. isBOnly: $.setDifference(['$B', '$A'])
  817. })
  818. .end()
  819. assert.deepStrictEqual(result.data, [
  820. { isBOnly: [] },
  821. { isBOnly: [] },
  822. { isBOnly: [3] },
  823. { isBOnly: [3] },
  824. { isBOnly: [] },
  825. { isBOnly: [{}, []] },
  826. { isBOnly: [] },
  827. { isBOnly: [1] }
  828. ])
  829. })
  830. it('setEquals', async () => {
  831. const result = await db
  832. .collection(collectionName)
  833. .aggregate()
  834. .project({
  835. _id: 0,
  836. sameElements: $.setEquals(['$A', '$B'])
  837. })
  838. .end()
  839. assert.deepStrictEqual(result.data, [
  840. { sameElements: true },
  841. { sameElements: true },
  842. { sameElements: false },
  843. { sameElements: false },
  844. { sameElements: false },
  845. { sameElements: false },
  846. { sameElements: true },
  847. { sameElements: false }
  848. ])
  849. })
  850. it('setIntersection', async () => {
  851. const result = await db
  852. .collection(collectionName)
  853. .aggregate()
  854. .project({
  855. _id: 0,
  856. setIntersection: $.setIntersection(['$A', '$B'])
  857. })
  858. .end()
  859. assert.deepStrictEqual(result.data, [
  860. { setIntersection: [1, 2] },
  861. { setIntersection: [1, 2] },
  862. { setIntersection: [1, 2] },
  863. { setIntersection: [1] },
  864. { setIntersection: [] },
  865. { setIntersection: [] },
  866. { setIntersection: [] },
  867. { setIntersection: [] }
  868. ])
  869. })
  870. it('setIsSubset', async () => {
  871. const result = await db
  872. .collection(collectionName)
  873. .aggregate()
  874. .project({
  875. _id: 0,
  876. setIsSubset: $.setIsSubset(['$A', '$B'])
  877. })
  878. .end()
  879. assert.deepStrictEqual(result.data, [
  880. { setIsSubset: true },
  881. { setIsSubset: true },
  882. { setIsSubset: true },
  883. { setIsSubset: false },
  884. { setIsSubset: false },
  885. { setIsSubset: false },
  886. { setIsSubset: true },
  887. { setIsSubset: true }
  888. ])
  889. })
  890. it('setUnion', async () => {
  891. const result = await db
  892. .collection(collectionName)
  893. .aggregate()
  894. .project({
  895. _id: 0,
  896. setUnion: $.setUnion(['$A', '$B'])
  897. })
  898. .end()
  899. assert.deepStrictEqual(result.data, [
  900. { setUnion: [1, 2] },
  901. { setUnion: [1, 2] },
  902. { setUnion: [1, 2, 3] },
  903. { setUnion: [1, 2, 3] },
  904. { setUnion: [1, 2] },
  905. { setUnion: [1, 2, {}, []] },
  906. { setUnion: [] },
  907. { setUnion: [1] }
  908. ])
  909. })
  910. })