PageRenderTime 45ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/MongoDB.Driver.Tests/Linq/MongoQueryableTests.cs

http://github.com/mongodb/mongo-csharp-driver
C# | 832 lines | 667 code | 163 blank | 2 comment | 27 complexity | ee64aa2a0ee493a76c1c8a4f0001b5ec MD5 | raw file
Possible License(s): Apache-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using MongoDB.Bson;
  7. using MongoDB.Bson.Serialization.Attributes;
  8. using MongoDB.Driver.Linq;
  9. using FluentAssertions;
  10. using NUnit.Framework;
  11. namespace MongoDB.Driver.Tests.Linq
  12. {
  13. [TestFixture]
  14. public class MongoQueryableTests : IntegrationTestBase
  15. {
  16. [Test]
  17. public void Any()
  18. {
  19. var result = CreateQuery().Any();
  20. result.Should().BeTrue();
  21. }
  22. [Test]
  23. public void Any_with_predicate()
  24. {
  25. var result = CreateQuery().Any(x => x.C.E.F == 234124);
  26. result.Should().BeFalse();
  27. result = CreateQuery().Any(x => x.C.E.F == 11);
  28. result.Should().BeTrue();
  29. }
  30. [Test]
  31. public async Task AnyAsync()
  32. {
  33. var result = await CreateQuery().AnyAsync();
  34. result.Should().BeTrue();
  35. }
  36. [Test]
  37. public async Task AnyAsync_with_predicate()
  38. {
  39. var result = await CreateQuery().AnyAsync(x => x.C.E.F == 234124);
  40. result.Should().BeFalse();
  41. result = await CreateQuery().AnyAsync(x => x.C.E.F == 11);
  42. result.Should().BeTrue();
  43. }
  44. [Test]
  45. public void Average()
  46. {
  47. var result = CreateQuery().Select(x => x.C.E.F).Average();
  48. result.Should().Be(61);
  49. }
  50. [Test]
  51. public void Average_with_selector()
  52. {
  53. var result = CreateQuery().Average(x => x.C.E.F);
  54. result.Should().Be(61);
  55. }
  56. [Test]
  57. public async Task AverageAsync()
  58. {
  59. var result = await CreateQuery().Select(x => x.C.E.F).AverageAsync();
  60. result.Should().Be(61);
  61. }
  62. [Test]
  63. public async Task AverageAsync_with_selector()
  64. {
  65. var result = await CreateQuery().AverageAsync(x => x.C.E.F);
  66. result.Should().Be(61);
  67. }
  68. [Test]
  69. public void Count()
  70. {
  71. var result = CreateQuery().Count();
  72. result.Should().Be(2);
  73. }
  74. [Test]
  75. public void Count_with_predicate()
  76. {
  77. var result = CreateQuery().Count(x => x.C.E.F == 11);
  78. result.Should().Be(1);
  79. }
  80. [Test]
  81. public async Task CountAsync()
  82. {
  83. var result = await CreateQuery().CountAsync();
  84. result.Should().Be(2);
  85. }
  86. [Test]
  87. public async Task CountAsync_with_predicate()
  88. {
  89. var result = await CreateQuery().CountAsync(x => x.C.E.F == 11);
  90. result.Should().Be(1);
  91. }
  92. [Test]
  93. public void Distinct()
  94. {
  95. var query = CreateQuery().Select(x => x.C.E.F).Distinct();
  96. Assert(query,
  97. 2,
  98. "{ $project: { 'C.E.F': 1, _id: 0 } }",
  99. "{ $group: { _id: '$C.E.F' } }");
  100. }
  101. [Test]
  102. public void First()
  103. {
  104. var result = CreateQuery().Select(x => x.C.E.F).First();
  105. result.Should().Be(11);
  106. }
  107. [Test]
  108. public void First_with_predicate()
  109. {
  110. var result = CreateQuery().Select(x => x.C.E.F).First(x => x == 11);
  111. result.Should().Be(11);
  112. }
  113. [Test]
  114. public async Task FirstAsync()
  115. {
  116. var result = await CreateQuery().Select(x => x.C.E.F).FirstAsync();
  117. result.Should().Be(11);
  118. }
  119. [Test]
  120. public async Task FirstAsync_with_predicate()
  121. {
  122. var result = await CreateQuery().Select(x => x.C.E.F).FirstAsync(x => x == 11);
  123. result.Should().Be(11);
  124. }
  125. [Test]
  126. public void FirstOrDefault()
  127. {
  128. var result = CreateQuery().Select(x => x.C.E.F).FirstOrDefault();
  129. result.Should().Be(11);
  130. }
  131. [Test]
  132. public void FirstOrDefault_with_predicate()
  133. {
  134. var result = CreateQuery().Select(x => x.C.E.F).FirstOrDefault(x => x == 11);
  135. result.Should().Be(11);
  136. }
  137. [Test]
  138. public async Task FirstOrDefaultAsync()
  139. {
  140. var result = await CreateQuery().Select(x => x.C.E.F).FirstOrDefaultAsync();
  141. result.Should().Be(11);
  142. }
  143. [Test]
  144. public async Task FirstOrDefaultAsync_with_predicate()
  145. {
  146. var result = await CreateQuery().Select(x => x.C.E.F).FirstOrDefaultAsync(x => x == 11);
  147. result.Should().Be(11);
  148. }
  149. [Test]
  150. public void GroupBy_method()
  151. {
  152. var query = CreateQuery()
  153. .GroupBy(x => x.A);
  154. Assert(query,
  155. 2,
  156. "{ $group: { _id: '$A' } }");
  157. }
  158. [Test]
  159. public void GroupBy_groupby_method()
  160. {
  161. var query = CreateQuery()
  162. .GroupBy(x => x.A)
  163. .GroupBy(g => g.First().B);
  164. Assert(query,
  165. 2,
  166. "{ $group: { _id: '$A', __agg0: { $first: '$B'} } }",
  167. "{ $group: { _id: '$__agg0' } }");
  168. }
  169. [Test]
  170. [Ignore("Does not work - use a project in the middle")]
  171. public void GroupBy_groupby_where_with_nested_accumulators_method()
  172. {
  173. var query = CreateQuery()
  174. .GroupBy(x => x.A)
  175. .GroupBy(g => g.First().B)
  176. .Where(g2 => g2.Average(g => g.Sum(x => x.C.E.F)) == 10);
  177. Assert(query,
  178. 1,
  179. "{ $group: { _id: '$A', __agg0: { $first: '$B' }, __agg1: { $sum: '$C.E.F'} } }",
  180. "{ $group: { _id: '$__agg0', _agg0: { $avg: '$__agg1' } } }",
  181. "{ $match: { _agg0: 10 } }");
  182. }
  183. [Test]
  184. public void GroupBy_select_anonymous_type_method()
  185. {
  186. var query = CreateQuery()
  187. .GroupBy(x => x.A)
  188. .Select(g => new { Key = g.Key, FirstB = g.First().B });
  189. Assert(query,
  190. 2,
  191. "{ $group: { _id: '$A', __agg0: { $first: '$B'} } }",
  192. "{ $project: { Key: '$_id', FirstB: '$__agg0', _id: 0 } }");
  193. }
  194. [Test]
  195. public void GroupBy_select_anonymous_type_syntax()
  196. {
  197. var query = from p in CreateQuery()
  198. group p by p.A into g
  199. select new { g.Key, FirstB = g.First().B };
  200. Assert(query,
  201. 2,
  202. "{ $group: { _id: '$A', __agg0: { $first: '$B'} } }",
  203. "{ $project: { Key: '$_id', FirstB: '$__agg0', _id: 0 } }");
  204. }
  205. [Test]
  206. public void GroupBy_where_method()
  207. {
  208. var query = CreateQuery()
  209. .GroupBy(x => x.A)
  210. .Where(g => g.Key == "Awesome");
  211. Assert(query,
  212. 1,
  213. "{ $group: { _id: '$A' } }",
  214. "{ $match: { _id: 'Awesome' } }");
  215. }
  216. [Test]
  217. public void GroupBy_where_with_accumulator_method()
  218. {
  219. var query = CreateQuery()
  220. .GroupBy(x => x.A)
  221. .Where(g => g.First().B == "Balloon");
  222. Assert(query,
  223. 1,
  224. "{ $group: { _id: '$A', __agg0: { $first: '$B' } } }",
  225. "{ $match: { __agg0: 'Balloon' } }");
  226. }
  227. [Test]
  228. public void GroupBy_where_select_anonymous_type_with_duplicate_accumulators_method()
  229. {
  230. var query = CreateQuery()
  231. .GroupBy(x => x.A)
  232. .Where(g => g.First().B == "Balloon")
  233. .Select(x => new { x.Key, FirstB = x.First().B });
  234. Assert(query,
  235. 1,
  236. "{ $group: { _id: '$A', __agg0: { $first: '$B'} } }",
  237. "{ $match: { __agg0: 'Balloon' } }",
  238. "{ $project: { Key: '$_id', FirstB: '$__agg0', _id: 0 } }");
  239. }
  240. [Test]
  241. public void GroupBy_where_select_anonymous_type_with_duplicate_accumulators_syntax()
  242. {
  243. var query = from p in CreateQuery()
  244. group p by p.A into g
  245. where g.First().B == "Balloon"
  246. select new { g.Key, FirstB = g.First().B };
  247. Assert(query,
  248. 1,
  249. "{ $group: { _id: '$A', __agg0: { $first: '$B'} } }",
  250. "{ $match: { __agg0: 'Balloon' } }",
  251. "{ $project: { Key: '$_id', FirstB: '$__agg0', _id: 0 } }");
  252. }
  253. [Test]
  254. public void GroupBy_with_resultSelector_anonymous_type_method()
  255. {
  256. var query = CreateQuery()
  257. .GroupBy(x => x.A, (k, s) => new { Key = k, FirstB = s.First().B });
  258. Assert(query,
  259. 2,
  260. "{ $group: { _id: '$A', FirstB: { $first: '$B'} } }");
  261. }
  262. [Test]
  263. public void Max()
  264. {
  265. var result = CreateQuery().Select(x => x.C.E.F).Max();
  266. result.Should().Be(111);
  267. }
  268. [Test]
  269. public void Max_with_selector()
  270. {
  271. var result = CreateQuery().Max(x => x.C.E.F);
  272. result.Should().Be(111);
  273. }
  274. [Test]
  275. public async Task MaxAsync()
  276. {
  277. var result = await CreateQuery().Select(x => x.C.E.F).MaxAsync();
  278. result.Should().Be(111);
  279. }
  280. [Test]
  281. public async Task MaxAsync_with_selector()
  282. {
  283. var result = await CreateQuery().MaxAsync(x => x.C.E.F);
  284. result.Should().Be(111);
  285. }
  286. [Test]
  287. public void Min()
  288. {
  289. var result = CreateQuery().Select(x => x.C.E.F).Min();
  290. result.Should().Be(11);
  291. }
  292. [Test]
  293. public void Min_with_selector()
  294. {
  295. var result = CreateQuery().Min(x => x.C.E.F);
  296. result.Should().Be(11);
  297. }
  298. [Test]
  299. public async Task MinAsync()
  300. {
  301. var result = await CreateQuery().Select(x => x.C.E.F).MinAsync();
  302. result.Should().Be(11);
  303. }
  304. [Test]
  305. public async Task MinAsync_with_selector()
  306. {
  307. var result = await CreateQuery().MinAsync(x => x.C.E.F);
  308. result.Should().Be(11);
  309. }
  310. [Test]
  311. public void OfType()
  312. {
  313. var query = CreateQuery().OfType<RootDescended>();
  314. Assert(query,
  315. 1,
  316. "{ $match: { _t: 'RootDescended' } }");
  317. }
  318. [Test]
  319. public void OrderBy_method()
  320. {
  321. var query = CreateQuery()
  322. .OrderBy(x => x.A);
  323. Assert(query,
  324. 2,
  325. "{ $sort: { A: 1 } }");
  326. }
  327. [Test]
  328. public void OrderBy_syntax()
  329. {
  330. var query = from x in CreateQuery()
  331. orderby x.A
  332. select x;
  333. Assert(query,
  334. 2,
  335. "{ $sort: { A: 1 } }");
  336. }
  337. [Test]
  338. public void OrderByDescending_method()
  339. {
  340. var query = CreateQuery()
  341. .OrderByDescending(x => x.A);
  342. Assert(query,
  343. 2,
  344. "{ $sort: { A: -1 } }");
  345. }
  346. [Test]
  347. public void OrderByDescending_syntax()
  348. {
  349. var query = from x in CreateQuery()
  350. orderby x.A descending
  351. select x;
  352. Assert(query,
  353. 2,
  354. "{ $sort: { A: -1 } }");
  355. }
  356. [Test]
  357. public void OrderBy_ThenBy_ThenByDescending_method()
  358. {
  359. var query = CreateQuery()
  360. .OrderBy(x => x.A)
  361. .ThenBy(x => x.B)
  362. .ThenByDescending(x => x.C);
  363. Assert(query,
  364. 2,
  365. "{ $sort: { A: 1, B: 1, C: -1 } }");
  366. }
  367. [Test]
  368. public void OrderBy_ThenBy_ThenByDescending_syntax()
  369. {
  370. var query = from x in CreateQuery()
  371. orderby x.A, x.B, x.C descending
  372. select x;
  373. Assert(query,
  374. 2,
  375. "{ $sort: { A: 1, B: 1, C: -1 } }");
  376. }
  377. [Test]
  378. public void OrderBy_ThenBy_ThenByDescending_with_redundant_fields_method()
  379. {
  380. var query = CreateQuery()
  381. .OrderBy(x => x.A)
  382. .ThenBy(x => x.B)
  383. .ThenBy(x => x.A);
  384. Assert(query,
  385. 2,
  386. "{ $sort: { A: 1, B: 1 } }");
  387. }
  388. [Test]
  389. public void OrderBy_ThenBy_ThenByDescending_with_redundant_fields_in_different_directions_method()
  390. {
  391. var query = CreateQuery()
  392. .OrderBy(x => x.A)
  393. .ThenBy(x => x.B)
  394. .ThenByDescending(x => x.A);
  395. Assert(query,
  396. 2,
  397. "{ $sort: { B: 1, A: -1 } }");
  398. }
  399. [Test]
  400. public void Select_anonymous_type_where_method()
  401. {
  402. var query = CreateQuery()
  403. .Select(x => new { Yeah = x.A })
  404. .Where(x => x.Yeah == "Awesome");
  405. Assert(query,
  406. 1,
  407. "{ $project: { Yeah: '$A', _id: 0 } }",
  408. "{ $match: { Yeah: 'Awesome' } }");
  409. }
  410. [Test]
  411. public void Select_scalar_where_method()
  412. {
  413. var query = CreateQuery()
  414. .Select(x => x.A)
  415. .Where(x => x == "Awesome");
  416. Assert(query,
  417. 1,
  418. "{ $project: { A: 1, _id: 0 } }",
  419. "{ $match: { A: 'Awesome' } }");
  420. }
  421. [Test]
  422. public void Select_anonymous_type_method()
  423. {
  424. var query = CreateQuery().Select(x => new { Yeah = x.A });
  425. Assert(query,
  426. 2,
  427. "{ $project: { Yeah: '$A', _id: 0 } }");
  428. }
  429. [Test]
  430. public void Select_anonymous_type_syntax()
  431. {
  432. var query = from x in CreateQuery()
  433. select new { Yeah = x.A };
  434. Assert(query,
  435. 2,
  436. "{ $project: { Yeah: '$A', _id: 0 } }");
  437. }
  438. [Test]
  439. public void Select_method_scalar()
  440. {
  441. var query = CreateQuery().Select(x => x.A);
  442. Assert(query,
  443. 2,
  444. "{ $project: { A: 1, _id: 0 } }");
  445. }
  446. [Test]
  447. public void Select_syntax_scalar()
  448. {
  449. var query = from x in CreateQuery()
  450. select x.A;
  451. Assert(query,
  452. 2,
  453. "{ $project: { A: 1, _id: 0 } }");
  454. }
  455. [Test]
  456. public void Select_method_computed_scalar()
  457. {
  458. var query = CreateQuery().Select(x => x.A + " " + x.B);
  459. Assert(query,
  460. 2,
  461. "{ $project: { __fld0: { $concat: ['$A', ' ', '$B'] }, _id: 0 } }");
  462. }
  463. [Test]
  464. public void Select_syntax_computed_scalar()
  465. {
  466. var query = from x in CreateQuery()
  467. select x.A + " " + x.B;
  468. Assert(query,
  469. 2,
  470. "{ $project: { __fld0: { $concat: ['$A', ' ', '$B'] }, _id: 0 } }");
  471. }
  472. [Test]
  473. public void SelectMany_with_only_resultSelector()
  474. {
  475. var query = CreateQuery()
  476. .SelectMany(x => x.G);
  477. Assert(query,
  478. 4,
  479. "{ $unwind: '$G' }",
  480. "{ $project: { G: 1, _id: 0 } }");
  481. }
  482. [Test]
  483. public void SelectMany_with_collection_selector_method_simple_scalar()
  484. {
  485. var query = CreateQuery()
  486. .SelectMany(x => x.G, (x, c) => c);
  487. Assert(query,
  488. 4,
  489. "{ $unwind: '$G' }",
  490. "{ $project: { G: 1, _id: 0 } }");
  491. }
  492. [Test]
  493. public void SelectMany_with_collection_selector_syntax_simple_scalar()
  494. {
  495. var query = from x in CreateQuery()
  496. from y in x.G
  497. select y;
  498. Assert(query,
  499. 4,
  500. "{ $unwind: '$G' }",
  501. "{ $project: { G: 1, _id: 0 } }");
  502. }
  503. [Test]
  504. public void SelectMany_with_collection_selector_method_computed_scalar()
  505. {
  506. var query = CreateQuery()
  507. .SelectMany(x => x.G, (x, c) => x.C.E.F + c.E.F + c.E.H);
  508. Assert(query,
  509. 4,
  510. "{ $unwind: '$G' }",
  511. "{ $project: { __fld0: { $add: ['$C.E.F', '$G.E.F', '$G.E.H'] }, _id: 0 } }");
  512. }
  513. [Test]
  514. public void SelectMany_with_collection_selector_syntax_computed_scalar()
  515. {
  516. var query = from x in CreateQuery()
  517. from y in x.G
  518. select x.C.E.F + y.E.F + y.E.H;
  519. Assert(query,
  520. 4,
  521. "{ $unwind: '$G' }",
  522. "{ $project: { __fld0: { $add: ['$C.E.F', '$G.E.F', '$G.E.H'] }, _id: 0 } }");
  523. }
  524. [Test]
  525. public void SelectMany_with_collection_selector_method_anonymous_type()
  526. {
  527. var query = CreateQuery()
  528. .SelectMany(x => x.G, (x, c) => new { x.C.E.F, Other = c.D });
  529. Assert(query,
  530. 4,
  531. "{ $unwind: '$G' }",
  532. "{ $project: { F: '$C.E.F', Other: '$G.D', _id: 0 } }");
  533. }
  534. [Test]
  535. public void SelectMany_with_collection_selector_syntax_anonymous_type()
  536. {
  537. var query = from x in CreateQuery()
  538. from y in x.G
  539. select new { x.C.E.F, Other = y.D };
  540. Assert(query,
  541. 4,
  542. "{ $unwind: '$G' }",
  543. "{ $project: { F: '$C.E.F', Other: '$G.D', _id: 0 } }");
  544. }
  545. [Test]
  546. public void Single()
  547. {
  548. var result = CreateQuery().Where(x => x.Id == 10).Select(x => x.C.E.F).Single();
  549. result.Should().Be(11);
  550. }
  551. [Test]
  552. public void Single_with_predicate()
  553. {
  554. var result = CreateQuery().Select(x => x.C.E.F).Single(x => x == 11);
  555. result.Should().Be(11);
  556. }
  557. [Test]
  558. public async Task SingleAsync()
  559. {
  560. var result = await CreateQuery().Where(x => x.Id == 10).Select(x => x.C.E.F).SingleAsync();
  561. result.Should().Be(11);
  562. }
  563. [Test]
  564. public async Task SingleAsync_with_predicate()
  565. {
  566. var result = await CreateQuery().Select(x => x.C.E.F).SingleAsync(x => x == 11);
  567. result.Should().Be(11);
  568. }
  569. [Test]
  570. public void SingleOrDefault()
  571. {
  572. var result = CreateQuery().Where(x => x.Id == 10).Select(x => x.C.E.F).SingleOrDefault();
  573. result.Should().Be(11);
  574. }
  575. [Test]
  576. public void SingleOrDefault_with_predicate()
  577. {
  578. var result = CreateQuery().Select(x => x.C.E.F).SingleOrDefault(x => x == 11);
  579. result.Should().Be(11);
  580. }
  581. [Test]
  582. public async Task SingleOrDefaultAsync()
  583. {
  584. var result = await CreateQuery().Where(x => x.Id == 10).Select(x => x.C.E.F).SingleOrDefaultAsync();
  585. result.Should().Be(11);
  586. }
  587. [Test]
  588. public async Task SingleOrDefaultAsync_with_predicate()
  589. {
  590. var result = await CreateQuery().Select(x => x.C.E.F).SingleOrDefaultAsync(x => x == 11);
  591. result.Should().Be(11);
  592. }
  593. [Test]
  594. public void Skip()
  595. {
  596. var query = CreateQuery().Skip(10);
  597. Assert(query,
  598. 0,
  599. "{ $skip: 10 }");
  600. }
  601. [Test]
  602. public void Sum()
  603. {
  604. var result = CreateQuery().Select(x => x.C.E.F).Sum();
  605. result.Should().Be(122);
  606. }
  607. [Test]
  608. public void Sum_with_selector()
  609. {
  610. var result = CreateQuery().Sum(x => x.C.E.F);
  611. result.Should().Be(122);
  612. }
  613. [Test]
  614. public async Task SumAsync()
  615. {
  616. var result = await CreateQuery().Select(x => x.C.E.F).SumAsync();
  617. result.Should().Be(122);
  618. }
  619. [Test]
  620. public async Task SumAsync_with_selector()
  621. {
  622. var result = await CreateQuery().SumAsync(x => x.C.E.F);
  623. result.Should().Be(122);
  624. }
  625. [Test]
  626. public void Take()
  627. {
  628. var query = CreateQuery().Take(1);
  629. Assert(query,
  630. 1,
  631. "{ $limit: 1 }");
  632. }
  633. [Test]
  634. public void Where_method()
  635. {
  636. var query = CreateQuery()
  637. .Where(x => x.A == "Awesome");
  638. Assert(query,
  639. 1,
  640. "{ $match: { A: 'Awesome' } }");
  641. }
  642. [Test]
  643. public void Where_syntax()
  644. {
  645. var query = from x in CreateQuery()
  646. where x.A == "Awesome"
  647. select x;
  648. Assert(query,
  649. 1,
  650. "{ $match: { A: 'Awesome' } }");
  651. }
  652. private List<T> Assert<T>(IMongoQueryable<T> queryable, int resultCount, params string[] expectedStages)
  653. {
  654. var stages = ((AggregateQueryableExecutionModel<T>)queryable.BuildExecutionModel()).Stages;
  655. CollectionAssert.AreEqual(expectedStages.Select(x => BsonDocument.Parse(x)).ToList(), stages);
  656. // async
  657. var results = queryable.ToListAsync().GetAwaiter().GetResult();
  658. results.Count.Should().Be(resultCount);
  659. // sync
  660. results = queryable.ToList();
  661. results.Count.Should().Be(resultCount);
  662. return results;
  663. }
  664. private IMongoQueryable<Root> CreateQuery()
  665. {
  666. return _collection.AsQueryable();
  667. }
  668. }
  669. }