PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/MongoDB.Driver.Tests/FilterDefinitionBuilderTests.cs

http://github.com/mongodb/mongo-csharp-driver
C# | 834 lines | 666 code | 154 blank | 14 comment | 11 complexity | e41a09f863691fe575836baeaa905827 MD5 | raw file
Possible License(s): Apache-2.0
  1. /* Copyright 2010-2014 MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using FluentAssertions;
  16. using MongoDB.Bson;
  17. using MongoDB.Bson.Serialization;
  18. using MongoDB.Bson.Serialization.Attributes;
  19. using MongoDB.Driver.GeoJsonObjectModel;
  20. using NUnit.Framework;
  21. namespace MongoDB.Driver.Tests
  22. {
  23. [TestFixture]
  24. public class FilterDefinitionBuilderTests
  25. {
  26. [Test]
  27. public void All()
  28. {
  29. var subject = CreateSubject<BsonDocument>();
  30. Assert(subject.All("x", new[] { 10, 20 }), "{x: {$all: [10,20]}}");
  31. }
  32. [Test]
  33. public void All_Typed()
  34. {
  35. var subject = CreateSubject<Person>();
  36. Assert(subject.All(x => x.FavoriteColors, new[] { "blue", "green" }), "{colors: {$all: ['blue','green']}}");
  37. Assert(subject.All("FavoriteColors", new[] { "blue", "green" }), "{colors: {$all: ['blue','green']}}");
  38. }
  39. [Test]
  40. public void And()
  41. {
  42. var subject = CreateSubject<BsonDocument>();
  43. var filter = subject.And(
  44. subject.Eq("a", 1),
  45. subject.Eq("b", 2));
  46. Assert(filter, "{a: 1, b: 2}");
  47. }
  48. [Test]
  49. public void And_with_clashing_keys_should_get_promoted_to_dollar_form()
  50. {
  51. var subject = CreateSubject<BsonDocument>();
  52. var filter = subject.And(
  53. subject.Eq("a", 1),
  54. subject.Eq("a", 2));
  55. Assert(filter, "{$and: [{a: 1}, {a: 2}]}");
  56. }
  57. [Test]
  58. public void And_with_clashing_keys_but_different_operators_should_get_merged()
  59. {
  60. var subject = CreateSubject<BsonDocument>();
  61. var filter = subject.And(
  62. subject.Gt("a", 1),
  63. subject.Lt("a", 10));
  64. Assert(filter, "{a: {$gt: 1, $lt: 10}}");
  65. }
  66. [Test]
  67. public void And_with_an_empty_filter()
  68. {
  69. var subject = CreateSubject<BsonDocument>();
  70. var filter = subject.And(
  71. "{}",
  72. subject.Eq("a", 10));
  73. Assert(filter, "{a: 10}");
  74. }
  75. [Test]
  76. public void And_with_a_nested_and_should_get_flattened()
  77. {
  78. var subject = CreateSubject<BsonDocument>();
  79. var filter = subject.And(
  80. subject.And("{a: 1}", new BsonDocument("b", 2)),
  81. subject.Eq("c", 3));
  82. Assert(filter, "{a: 1, b: 2, c: 3}");
  83. }
  84. [Test]
  85. public void And_with_a_nested_and_and_clashing_keys()
  86. {
  87. var subject = CreateSubject<BsonDocument>();
  88. var filter = subject.And(
  89. subject.And(subject.Eq("a", 1), subject.Eq("a", 2)),
  90. subject.Eq("c", 3));
  91. Assert(filter, "{$and: [{a: 1}, {a: 2}, {c: 3}]}");
  92. }
  93. [Test]
  94. public void And_with_a_nested_and_and_clashing_operators_on_the_same_key()
  95. {
  96. var subject = CreateSubject<BsonDocument>();
  97. var filter = subject.Lt("a", 1) & subject.Lt("a", 2);
  98. Assert(filter, "{$and: [{a: {$lt: 1}}, {a: {$lt: 2}}]}");
  99. }
  100. [Test]
  101. public void And_with_a_nested_and_and_clashing_keys_using_ampersand()
  102. {
  103. var subject = CreateSubject<BsonDocument>();
  104. var filter = subject.Eq("a", 1) & "{a: 2}" & new BsonDocument("c", 3);
  105. Assert(filter, "{$and: [{a: 1}, {a: 2}, {c: 3}]}");
  106. }
  107. [Test]
  108. public void ElemMatch()
  109. {
  110. var subject = CreateSubject<BsonDocument>();
  111. Assert(subject.ElemMatch<BsonDocument>("a", "{b: 1}"), "{a: {$elemMatch: {b: 1}}}");
  112. }
  113. [Test]
  114. public void ElemMatch_Typed()
  115. {
  116. var subject = CreateSubject<Person>();
  117. Assert(subject.ElemMatch<Pet>("Pets", "{Name: 'Fluffy'}"), "{pets: {$elemMatch: {Name: 'Fluffy'}}}");
  118. Assert(subject.ElemMatch(x => x.Pets, "{Name: 'Fluffy'}"), "{pets: {$elemMatch: {Name: 'Fluffy'}}}");
  119. Assert(subject.ElemMatch(x => x.Pets, x => x.Name == "Fluffy"), "{pets: {$elemMatch: {name: 'Fluffy'}}}");
  120. }
  121. [Test]
  122. public void Empty()
  123. {
  124. var subject = CreateSubject<BsonDocument>();
  125. Assert(subject.Empty, "{}");
  126. }
  127. [Test]
  128. public void Empty_Typed()
  129. {
  130. var subject = CreateSubject<Person>();
  131. Assert(subject.Empty, "{}");
  132. }
  133. [Test]
  134. public void Eq()
  135. {
  136. var subject = CreateSubject<BsonDocument>();
  137. Assert(subject.Eq("x", 10), "{x: 10}");
  138. Assert(subject.AnyEq("x", 10), "{x: 10}");
  139. }
  140. [Test]
  141. public void Eq_Typed()
  142. {
  143. var subject = CreateSubject<Person>();
  144. Assert(subject.Eq(x => x.FirstName, "Jack"), "{fn: 'Jack'}");
  145. Assert(subject.Eq("FirstName", "Jim"), "{fn: 'Jim'}");
  146. Assert(subject.Eq("firstName", "Jim"), "{firstName: 'Jim'}");
  147. Assert(subject.Eq(x => x.FavoriteColors, new[] { "yellow", "green" }), "{colors: ['yellow', 'green']}");
  148. Assert(subject.Eq("FavoriteColors", new[] { "yellow", "green" }), "{colors: ['yellow', 'green']}");
  149. Assert(subject.AnyEq(x => x.FavoriteColors, "yellow"), "{colors: 'yellow'}");
  150. Assert(subject.AnyEq("FavoriteColors", "yellow"), "{colors: 'yellow'}");
  151. }
  152. [Test]
  153. public void Exists()
  154. {
  155. var subject = CreateSubject<BsonDocument>();
  156. Assert(subject.Exists("x"), "{x: {$exists: true}}");
  157. Assert(subject.Exists("x", false), "{x: {$exists: false}}");
  158. }
  159. [Test]
  160. public void Exists_Typed()
  161. {
  162. var subject = CreateSubject<Person>();
  163. Assert(subject.Exists(x => x.FirstName), "{fn: {$exists: true}}");
  164. Assert(subject.Exists("FirstName", false), "{fn: {$exists: false}}");
  165. }
  166. [Test]
  167. public void Expression()
  168. {
  169. var subject = CreateSubject<Person>();
  170. Assert(subject.Where(x => x.FirstName == "Jack" && x.Age > 10), "{fn: 'Jack', age: {$gt: 10}}");
  171. }
  172. [Test]
  173. public void GeoIntersects()
  174. {
  175. var subject = CreateSubject<BsonDocument>();
  176. var poly = GeoJson.Polygon(
  177. GeoJson.Geographic(40, 18),
  178. GeoJson.Geographic(40, 19),
  179. GeoJson.Geographic(41, 19),
  180. GeoJson.Geographic(40, 18));
  181. Assert(subject.GeoIntersects("x", poly), "{x: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  182. }
  183. [Test]
  184. public void GeoIntersects_Typed()
  185. {
  186. var subject = CreateSubject<Person>();
  187. var poly = GeoJson.Polygon(
  188. GeoJson.Geographic(40, 18),
  189. GeoJson.Geographic(40, 19),
  190. GeoJson.Geographic(41, 19),
  191. GeoJson.Geographic(40, 18));
  192. Assert(subject.GeoIntersects(x => x.Location, poly), "{loc: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  193. Assert(subject.GeoIntersects("Location", poly), "{loc: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  194. }
  195. [Test]
  196. public void GeoIntersects_Typed_with_GeoJson()
  197. {
  198. var subject = CreateSubject<Person>();
  199. var poly = GeoJson.Polygon(
  200. GeoJson.Geographic(40, 18),
  201. GeoJson.Geographic(40, 19),
  202. GeoJson.Geographic(41, 19),
  203. GeoJson.Geographic(40, 18));
  204. Assert(subject.GeoIntersects(x => x.Location, poly), "{loc: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  205. Assert(subject.GeoIntersects("Location", poly), "{loc: {$geoIntersects: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  206. }
  207. [Test]
  208. public void GeoWithin()
  209. {
  210. var subject = CreateSubject<BsonDocument>();
  211. var poly = GeoJson.Polygon(
  212. GeoJson.Geographic(40, 18),
  213. GeoJson.Geographic(40, 19),
  214. GeoJson.Geographic(41, 19),
  215. GeoJson.Geographic(40, 18));
  216. Assert(subject.GeoWithin("x", poly), "{x: {$geoWithin: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  217. }
  218. [Test]
  219. public void GeoWithin_Typed()
  220. {
  221. var subject = CreateSubject<Person>();
  222. var poly = GeoJson.Polygon(
  223. GeoJson.Geographic(40, 18),
  224. GeoJson.Geographic(40, 19),
  225. GeoJson.Geographic(41, 19),
  226. GeoJson.Geographic(40, 18));
  227. Assert(subject.GeoWithin(x => x.Location, poly), "{loc: {$geoWithin: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  228. Assert(subject.GeoWithin("Location", poly), "{loc: {$geoWithin: {$geometry: {type: 'Polygon', coordinates: [[[40.0, 18.0], [40.0, 19.0], [41.0, 19.0], [40.0, 18.0]]]}}}}");
  229. }
  230. [Test]
  231. public void GeoWithinBox()
  232. {
  233. var subject = CreateSubject<BsonDocument>();
  234. Assert(subject.GeoWithinBox("x", 10, 20, 30, 40), "{x: {$geoWithin: {$box: [[10.0, 20.0], [30.0, 40.0]]}}}");
  235. }
  236. [Test]
  237. public void GeoWithinBox_Typed()
  238. {
  239. var subject = CreateSubject<Person>();
  240. Assert(subject.GeoWithinBox(x => x.Location, 10, 20, 30, 40), "{loc: {$geoWithin: {$box: [[10.0, 20.0], [30.0, 40.0]]}}}");
  241. Assert(subject.GeoWithinBox("Location", 10, 20, 30, 40), "{loc: {$geoWithin: {$box: [[10.0, 20.0], [30.0, 40.0]]}}}");
  242. }
  243. [Test]
  244. public void GeoWithinCenter()
  245. {
  246. var subject = CreateSubject<BsonDocument>();
  247. Assert(subject.GeoWithinCenter("x", 10, 20, 30), "{x: {$geoWithin: {$center: [[10.0, 20.0], 30.0]}}}");
  248. }
  249. [Test]
  250. public void GeoWithinCenter_Typed()
  251. {
  252. var subject = CreateSubject<Person>();
  253. Assert(subject.GeoWithinCenter(x => x.Location, 10, 20, 30), "{loc: {$geoWithin: {$center: [[10.0, 20.0], 30.0]}}}");
  254. Assert(subject.GeoWithinCenter("Location", 10, 20, 30), "{loc: {$geoWithin: {$center: [[10.0, 20.0], 30.0]}}}");
  255. }
  256. [Test]
  257. public void GeoWithinCenterSphere()
  258. {
  259. var subject = CreateSubject<BsonDocument>();
  260. Assert(subject.GeoWithinCenterSphere("x", 10, 20, 30), "{x: {$geoWithin: {$centerSphere: [[10.0, 20.0], 30.0]}}}");
  261. }
  262. [Test]
  263. public void GeoWithinCenterSphere_Typed()
  264. {
  265. var subject = CreateSubject<Person>();
  266. Assert(subject.GeoWithinCenterSphere(x => x.Location, 10, 20, 30), "{loc: {$geoWithin: {$centerSphere: [[10.0, 20.0], 30.0]}}}");
  267. Assert(subject.GeoWithinCenterSphere("Location", 10, 20, 30), "{loc: {$geoWithin: {$centerSphere: [[10.0, 20.0], 30.0]}}}");
  268. }
  269. [Test]
  270. public void GeoWithinPolygon()
  271. {
  272. var subject = CreateSubject<BsonDocument>();
  273. Assert(subject.GeoWithinPolygon("x", new[,] { { 1d, 2d }, { 3d, 4d } }), "{x: {$geoWithin: {$polygon: [[1.0, 2.0], [3.0, 4.0]]}}}");
  274. }
  275. [Test]
  276. public void GeoWithinPolygon_Typed()
  277. {
  278. var subject = CreateSubject<Person>();
  279. Assert(subject.GeoWithinPolygon(x => x.Location, new[,] { { 1d, 2d }, { 3d, 4d } }), "{loc: {$geoWithin: {$polygon: [[1.0, 2.0], [3.0, 4.0]]}}}");
  280. Assert(subject.GeoWithinPolygon("Location", new[,] { { 1d, 2d }, { 3d, 4d } }), "{loc: {$geoWithin: {$polygon: [[1.0, 2.0], [3.0, 4.0]]}}}");
  281. }
  282. [Test]
  283. public void GreaterThan()
  284. {
  285. var subject = CreateSubject<BsonDocument>();
  286. Assert(subject.Gt("x", 10), "{x: {$gt: 10}}");
  287. Assert(subject.AnyGt("x", 10), "{x: {$gt: 10}}");
  288. }
  289. [Test]
  290. public void GreaterThan_Typed()
  291. {
  292. var subject = CreateSubject<Person>();
  293. Assert(subject.Gt(x => x.Age, 10), "{age: {$gt: 10}}");
  294. Assert(subject.Gt("Age", 10), "{age: {$gt: 10}}");
  295. Assert(subject.AnyGt(x => x.FavoriteColors, "green"), "{colors: {$gt: 'green'}}");
  296. Assert(subject.AnyGt("FavoriteColors", "green"), "{colors: {$gt: 'green'}}");
  297. }
  298. [Test]
  299. public void GreaterThanOrEqual()
  300. {
  301. var subject = CreateSubject<BsonDocument>();
  302. Assert(subject.Gte("x", 10), "{x: {$gte: 10}}");
  303. Assert(subject.AnyGte("x", 10), "{x: {$gte: 10}}");
  304. }
  305. [Test]
  306. public void GreaterThanOrEqual_Typed()
  307. {
  308. var subject = CreateSubject<Person>();
  309. Assert(subject.Gte(x => x.Age, 10), "{age: {$gte: 10}}");
  310. Assert(subject.Gte("Age", 10), "{age: {$gte: 10}}");
  311. Assert(subject.AnyGte(x => x.FavoriteColors, "green"), "{colors: {$gte: 'green'}}");
  312. Assert(subject.AnyGte("FavoriteColors", "green"), "{colors: {$gte: 'green'}}");
  313. }
  314. [Test]
  315. public void In()
  316. {
  317. var subject = CreateSubject<BsonDocument>();
  318. Assert(subject.In("x", new[] { 10, 20 }), "{x: {$in: [10,20]}}");
  319. Assert(subject.AnyIn("x", new[] { 10, 20 }), "{x: {$in: [10,20]}}");
  320. }
  321. [Test]
  322. public void In_Typed()
  323. {
  324. var subject = CreateSubject<Person>();
  325. Assert(subject.In(x => x.Age, new[] { 10, 20 }), "{age: {$in: [10, 20]}}");
  326. Assert(subject.In("Age", new[] { 10, 20 }), "{age: {$in: [10, 20]}}");
  327. Assert(subject.AnyIn(x => x.FavoriteColors, new[] { "blue", "green" }), "{colors: {$in: ['blue','green']}}");
  328. Assert(subject.AnyIn("FavoriteColors", new[] { "blue", "green" }), "{colors: {$in: ['blue','green']}}");
  329. }
  330. [Test]
  331. public void Lt()
  332. {
  333. var subject = CreateSubject<BsonDocument>();
  334. Assert(subject.Lt("x", 10), "{x: {$lt: 10}}");
  335. Assert(subject.AnyLt("x", 10), "{x: {$lt: 10}}");
  336. }
  337. [Test]
  338. public void Lt_Typed()
  339. {
  340. var subject = CreateSubject<Person>();
  341. Assert(subject.Lt(x => x.Age, 10), "{age: {$lt: 10}}");
  342. Assert(subject.Lt("Age", 10), "{age: {$lt: 10}}");
  343. Assert(subject.AnyLt(x => x.FavoriteColors, "green"), "{colors: {$lt: 'green'}}");
  344. Assert(subject.AnyLt("FavoriteColors", "green"), "{colors: {$lt: 'green'}}");
  345. }
  346. [Test]
  347. public void Lte()
  348. {
  349. var subject = CreateSubject<BsonDocument>();
  350. Assert(subject.Lte("x", 10), "{x: {$lte: 10}}");
  351. Assert(subject.AnyLte("x", 10), "{x: {$lte: 10}}");
  352. }
  353. [Test]
  354. public void Lte_Typed()
  355. {
  356. var subject = CreateSubject<Person>();
  357. Assert(subject.Lte(x => x.Age, 10), "{age: {$lte: 10}}");
  358. Assert(subject.Lte("Age", 10), "{age: {$lte: 10}}");
  359. Assert(subject.AnyLte(x => x.FavoriteColors, "green"), "{colors: {$lte: 'green'}}");
  360. Assert(subject.AnyLte("FavoriteColors", "green"), "{colors: {$lte: 'green'}}");
  361. }
  362. [Test]
  363. public void Mod()
  364. {
  365. var subject = CreateSubject<BsonDocument>();
  366. Assert(subject.Mod("x", 10, 4), "{x: {$mod: [NumberLong(10), NumberLong(4)]}}");
  367. }
  368. [Test]
  369. public void Mod_Typed()
  370. {
  371. var subject = CreateSubject<Person>();
  372. Assert(subject.Mod(x => x.Age, 10, 4), "{age: {$mod: [NumberLong(10), NumberLong(4)]}}");
  373. Assert(subject.Mod("Age", 10, 4), "{age: {$mod: [NumberLong(10), NumberLong(4)]}}");
  374. Assert(subject.Mod(x => x.FavoriteColors, 10, 4), "{colors: {$mod: [NumberLong(10), NumberLong(4)]}}");
  375. Assert(subject.Mod("FavoriteColors", 10, 4), "{colors: {$mod: [NumberLong(10), NumberLong(4)]}}");
  376. }
  377. [Test]
  378. public void Ne()
  379. {
  380. var subject = CreateSubject<BsonDocument>();
  381. Assert(subject.Ne("x", 10), "{x: {$ne: 10}}");
  382. Assert(subject.AnyNe("x", 10), "{x: {$ne: 10}}");
  383. }
  384. [Test]
  385. public void Ne_Typed()
  386. {
  387. var subject = CreateSubject<Person>();
  388. Assert(subject.Ne(x => x.Age, 10), "{age: {$ne: 10}}");
  389. Assert(subject.Ne("Age", 10), "{age: {$ne: 10}}");
  390. Assert(subject.AnyNe(x => x.FavoriteColors, "green"), "{colors: {$ne: 'green'}}");
  391. Assert(subject.AnyNe("FavoriteColors", "green"), "{colors: {$ne: 'green'}}");
  392. }
  393. [Test]
  394. public void Near(
  395. [Values(null, 10d)] double? maxDistance,
  396. [Values(null, 20d)] double? minDistance)
  397. {
  398. var subject = CreateSubject<BsonDocument>();
  399. var filter = subject.Near("x", 40, 18, maxDistance, minDistance);
  400. var expectedNear = BsonDocument.Parse("{$near: [40.0, 18.0]}");
  401. if (maxDistance.HasValue)
  402. {
  403. expectedNear.Add("$maxDistance", maxDistance.Value);
  404. }
  405. if (minDistance.HasValue)
  406. {
  407. expectedNear.Add("$minDistance", minDistance.Value);
  408. }
  409. var expected = new BsonDocument("x", expectedNear);
  410. Assert(filter, expected);
  411. }
  412. [Test]
  413. public void Near_with_GeoJson(
  414. [Values(null, 10d)] double? maxDistance,
  415. [Values(null, 20d)] double? minDistance)
  416. {
  417. var subject = CreateSubject<BsonDocument>();
  418. var point = GeoJson.Point(GeoJson.Geographic(40, 18));
  419. var filter = subject.Near("x", point, maxDistance, minDistance);
  420. var expectedNearCondition = BsonDocument.Parse("{$geometry: {type: 'Point', coordinates: [40.0, 18.0]}}");
  421. if (maxDistance.HasValue)
  422. {
  423. expectedNearCondition.Add("$maxDistance", maxDistance.Value);
  424. }
  425. if (minDistance.HasValue)
  426. {
  427. expectedNearCondition.Add("$minDistance", minDistance.Value);
  428. }
  429. var expectedNear = new BsonDocument("$near", expectedNearCondition);
  430. var expected = new BsonDocument("x", expectedNear);
  431. Assert(filter, expected);
  432. }
  433. [Test]
  434. public void NearSphere(
  435. [Values(null, 10d)] double? maxDistance,
  436. [Values(null, 20d)] double? minDistance)
  437. {
  438. var subject = CreateSubject<BsonDocument>();
  439. var filter = subject.NearSphere("x", 40, 18, maxDistance, minDistance);
  440. var expectedNear = BsonDocument.Parse("{$nearSphere: [40.0, 18.0]}");
  441. if (maxDistance.HasValue)
  442. {
  443. expectedNear.Add("$maxDistance", maxDistance.Value);
  444. }
  445. if (minDistance.HasValue)
  446. {
  447. expectedNear.Add("$minDistance", minDistance.Value);
  448. }
  449. var expected = new BsonDocument("x", expectedNear);
  450. Assert(filter, expected);
  451. }
  452. [Test]
  453. public void NearSphere_with_GeoJson(
  454. [Values(null, 10d)] double? maxDistance,
  455. [Values(null, 20d)] double? minDistance)
  456. {
  457. var subject = CreateSubject<BsonDocument>();
  458. var point = GeoJson.Point(GeoJson.Geographic(40, 18));
  459. var filter = subject.NearSphere("x", point, maxDistance, minDistance);
  460. var expectedNearCondition = BsonDocument.Parse("{$geometry: {type: 'Point', coordinates: [40.0, 18.0]}}");
  461. if (maxDistance.HasValue)
  462. {
  463. expectedNearCondition.Add("$maxDistance", maxDistance.Value);
  464. }
  465. if (minDistance.HasValue)
  466. {
  467. expectedNearCondition.Add("$minDistance", minDistance.Value);
  468. }
  469. var expectedNear = new BsonDocument("$nearSphere", expectedNearCondition);
  470. var expected = new BsonDocument("x", expectedNear);
  471. Assert(filter, expected);
  472. }
  473. [Test]
  474. public void Nin()
  475. {
  476. var subject = CreateSubject<BsonDocument>();
  477. Assert(subject.Nin("x", new[] { 10, 20 }), "{x: {$nin: [10,20]}}");
  478. Assert(subject.AnyNin("x", new[] { 10, 20 }), "{x: {$nin: [10,20]}}");
  479. }
  480. [Test]
  481. public void Nin_Typed()
  482. {
  483. var subject = CreateSubject<Person>();
  484. Assert(subject.Nin(x => x.Age, new[] { 10, 20 }), "{age: {$nin: [10, 20]}}");
  485. Assert(subject.Nin("Age", new[] { 10, 20 }), "{age: {$nin: [10, 20]}}");
  486. Assert(subject.AnyNin(x => x.FavoriteColors, new[] { "blue", "green" }), "{colors: {$nin: ['blue','green']}}");
  487. Assert(subject.AnyNin("FavoriteColors", new[] { "blue", "green" }), "{colors: {$nin: ['blue','green']}}");
  488. }
  489. [Test]
  490. public void Not_with_and()
  491. {
  492. var subject = CreateSubject<BsonDocument>();
  493. var filter = subject.Not("{$and: [{a: 1}, {b: 2}]}");
  494. Assert(filter, "{$nor: [{$and: [{a: 1}, {b: 2}]}]}");
  495. }
  496. [Test]
  497. public void Not_with_equal()
  498. {
  499. var subject = CreateSubject<BsonDocument>();
  500. var filter = subject.Not("{a: 1}");
  501. Assert(filter, "{a: {$ne: 1}}");
  502. }
  503. [Test]
  504. public void Not_with_exists()
  505. {
  506. var subject = CreateSubject<BsonDocument>();
  507. var filter = subject.Not(subject.Exists("a"));
  508. Assert(filter, "{a: {$exists: false}}");
  509. var filter2 = subject.Not(subject.Exists("a", false));
  510. Assert(filter2, "{a: {$exists: true}}");
  511. }
  512. [Test]
  513. public void Not_with_in()
  514. {
  515. var subject = CreateSubject<BsonDocument>();
  516. var filter = subject.Not(subject.In("a", new[] { 10, 20 }));
  517. Assert(filter, "{a: {$nin: [10, 20]}}");
  518. }
  519. [Test]
  520. public void Not_with_not()
  521. {
  522. var subject = CreateSubject<BsonDocument>();
  523. var filter = subject.Not(subject.Not("{a: 1}"));
  524. Assert(filter, "{a: 1}");
  525. }
  526. [Test]
  527. public void Not_with_not_equal()
  528. {
  529. var subject = CreateSubject<BsonDocument>();
  530. var filter = subject.Not("{a: {$ne: 1}}");
  531. Assert(filter, "{a: 1}");
  532. }
  533. [Test]
  534. public void Not_with_not_in()
  535. {
  536. var subject = CreateSubject<BsonDocument>();
  537. var filter = subject.Not(subject.AnyNin("a", new[] { 10, 20 }));
  538. Assert(filter, "{a: {$in: [10, 20]}}");
  539. }
  540. [Test]
  541. public void Not_with_not_or()
  542. {
  543. var subject = CreateSubject<BsonDocument>();
  544. var filter = subject.Not("{$nor: [{a: 1}, {b: 2}]}");
  545. Assert(filter, "{$or: [{a: 1}, {b: 2}]}");
  546. }
  547. [Test]
  548. public void Not_with_or()
  549. {
  550. var subject = CreateSubject<BsonDocument>();
  551. var filter = subject.Not("{$or: [{a: 1}, {b: 2}]}");
  552. Assert(filter, "{$nor: [{a: 1}, {b: 2}]}");
  553. }
  554. [Test]
  555. public void Not_with_or_using_bang_operator()
  556. {
  557. var subject = CreateSubject<BsonDocument>();
  558. var filter = !(subject.Eq("a", 1) | "{b: 2}");
  559. Assert(filter, "{$nor: [{a: 1}, {b: 2}]}");
  560. }
  561. [Test]
  562. public void Or()
  563. {
  564. var subject = CreateSubject<BsonDocument>();
  565. var filter = subject.Or(
  566. "{a: 1}",
  567. new BsonDocument("b", 2));
  568. Assert(filter, "{$or: [{a: 1}, {b: 2}]}");
  569. }
  570. [Test]
  571. public void Or_should_flatten_nested_ors()
  572. {
  573. var subject = CreateSubject<BsonDocument>();
  574. var filter = subject.Or(
  575. "{$or: [{a: 1}, {b: 2}]}",
  576. new BsonDocument("c", 3));
  577. Assert(filter, "{$or: [{a: 1}, {b: 2}, {c: 3}]}");
  578. }
  579. [Test]
  580. public void Or_should_flatten_nested_ors_with_a_pipe()
  581. {
  582. var subject = CreateSubject<BsonDocument>();
  583. var filter = subject.Eq("a", 1) | "{b: 2}" | new BsonDocument("c", 3);
  584. Assert(filter, "{$or: [{a: 1}, {b: 2}, {c: 3}]}");
  585. }
  586. [Test]
  587. public void Regex()
  588. {
  589. var subject = CreateSubject<BsonDocument>();
  590. Assert(subject.Regex("x", "/abc/"), "{x: /abc/}");
  591. }
  592. [Test]
  593. public void Regex_Typed()
  594. {
  595. var subject = CreateSubject<Person>();
  596. Assert(subject.Regex(x => x.FirstName, "/abc/"), "{fn: /abc/}");
  597. Assert(subject.Regex("FirstName", "/abc/"), "{fn: /abc/}");
  598. Assert(subject.Regex(x => x.FavoriteColors, "/abc/"), "{colors: /abc/}");
  599. Assert(subject.Regex("FavoriteColors", "/abc/"), "{colors: /abc/}");
  600. }
  601. [Test]
  602. public void Size()
  603. {
  604. var subject = CreateSubject<BsonDocument>();
  605. Assert(subject.Size("x", 10), "{x: {$size: 10}}");
  606. }
  607. [Test]
  608. public void Size_Typed()
  609. {
  610. var subject = CreateSubject<Person>();
  611. Assert(subject.Size(x => x.FavoriteColors, 10), "{colors: {$size: 10}}");
  612. Assert(subject.Size("FavoriteColors", 10), "{colors: {$size: 10}}");
  613. }
  614. [Test]
  615. public void SizeGt()
  616. {
  617. var subject = CreateSubject<BsonDocument>();
  618. Assert(subject.SizeGt("x", 10), "{'x.10': {$exists: true}}");
  619. }
  620. [Test]
  621. public void SizeGt_Typed()
  622. {
  623. var subject = CreateSubject<Person>();
  624. Assert(subject.SizeGt(x => x.FavoriteColors, 10), "{'colors.10': {$exists: true}}");
  625. Assert(subject.SizeGt("FavoriteColors", 10), "{'colors.10': {$exists: true}}");
  626. }
  627. [Test]
  628. public void Text()
  629. {
  630. var subject = CreateSubject<BsonDocument>();
  631. Assert(subject.Text("funny"), "{$text: {$search: 'funny'}}");
  632. Assert(subject.Text("funny", "en"), "{$text: {$search: 'funny', $language: 'en'}}");
  633. }
  634. [Test]
  635. public void Type()
  636. {
  637. var subject = CreateSubject<BsonDocument>();
  638. Assert(subject.Type("x", BsonType.String), "{x: {$type: 2}}");
  639. }
  640. [Test]
  641. public void Type_Typed()
  642. {
  643. var subject = CreateSubject<Person>();
  644. Assert(subject.Type(x => x.FirstName, BsonType.String), "{fn: {$type: 2}}");
  645. Assert(subject.Type("FirstName", BsonType.String), "{fn: {$type: 2}}");
  646. }
  647. private void Assert<TDocument>(FilterDefinition<TDocument> filter, string expected)
  648. {
  649. Assert(filter, BsonDocument.Parse(expected));
  650. }
  651. private void Assert<TDocument>(FilterDefinition<TDocument> filter, BsonDocument expected)
  652. {
  653. var documentSerializer = BsonSerializer.SerializerRegistry.GetSerializer<TDocument>();
  654. var renderedFilter = filter.Render(documentSerializer, BsonSerializer.SerializerRegistry);
  655. renderedFilter.Should().Be(expected);
  656. }
  657. private FilterDefinitionBuilder<TDocument> CreateSubject<TDocument>()
  658. {
  659. return new FilterDefinitionBuilder<TDocument>();
  660. }
  661. private class Person
  662. {
  663. [BsonElement("fn")]
  664. public string FirstName { get; set; }
  665. [BsonElement("colors")]
  666. public string[] FavoriteColors { get; set; }
  667. [BsonElement("age")]
  668. public int Age { get; set; }
  669. [BsonElement("pets")]
  670. public Pet[] Pets { get; set; }
  671. [BsonElement("loc")]
  672. public int[] Location { get; set; }
  673. }
  674. private class Pet
  675. {
  676. [BsonElement("name")]
  677. public string Name { get; set; }
  678. }
  679. }
  680. }