1 module uim.mongo.filter; 2 3 import uim.mongo; 4 5 class DBsonFilter { 6 this() { 7 _bson = Bson.emptyObject; 8 } 9 this(T)(string field, T value) { 10 this(); 11 _bson[field] = Bson(value); 12 } 13 this(T)(T[string] values) { 14 this(); 15 _bson = value.toBson; 16 } 17 18 private Bson _bson; 19 20 /* 21 all() - creates an all filter for an array field. 22 */ 23 @safe O All(this O, T)(string field, T[] values) { 24 if (_bson[field].type != Bson.Type.null_) { 25 auto condition = _bson[field]; 26 condition["$all"] = values.toBson; 27 _bson[field] = condition; 28 } 29 else { 30 auto condition = Bson.emptyObject; 31 condition["$all"] = values.toBson; 32 _bson[field] = condition; 33 } 34 return cast(O)this; } 35 unittest{ 36 writeln(BsonFilter.All("fruits", ["apple", "melone"])); 37 } 38 39 /* 40 And() - creates an and field. 41 */ 42 @safe O And(this O, T)(string field, T value) { 43 _bson[field] = value; 44 return cast(O)this; 45 } 46 @safe O And(this O, T)(T[string] values) { 47 _bson = values.toBson; 48 return cast(O)this; 49 } 50 unittest{ 51 assert(BsonFilter.And(["a":"b"]) == `{"a":"b"}`); 52 assert(BsonFilter.And(["a":"b", "c": "d"]) == `{"c":"d","a":"b"}`); 53 } 54 55 /* 56 anyEq() - Creates an equality filter for an array field. 57 */ 58 @safe O anyEq(this O)() { 59 // TODO 60 return cast(O)this; 61 } 62 unittest{ 63 64 } 65 66 /* 67 anyGt() - Creates an greater than filter for an array field. 68 */ 69 @safe O Gt(this O, T)(string field, T value) { 70 if (_bson[field].type != Bson.Type.null_) { 71 auto condition = _bson[field]; 72 condition["$gt"] = Bson(value); 73 _bson[field] = condition; 74 } 75 else { 76 auto condition = Bson.emptyObject; 77 condition["$gt"] = Bson(value); 78 _bson[field] = condition; 79 } 80 return cast(O)this; 81 } 82 unittest{ 83 writeln(BsonFilter.Gt("age", 20)); 84 assert(BsonFilter.Gt("age", 20) == `{"age":{"$gt":20}}`); 85 assert(BsonFilter.Gt("age", 20).Gt("age", 40) == `{"age":{"$gt":40}}`); 86 } 87 88 /* 89 anyGe() - Creates an greater than or equal filter for an array field. 90 */ 91 @safe O anyGe(this O, T)(string field, string value) { 92 // TODO 93 return cast(O)this; 94 } 95 unittest{ 96 97 } 98 99 // $bitsAllClear 100 @safe O BitsAllClear(this O)(string field, BsonBinData data) { 101 auto condition = Bson.emptyObject; 102 condition["$bitsAllClear"] = data; 103 _bson[field] = condition; 104 return cast(O)this; 105 } 106 @safe O BitsAllClear(this O)(string field, int[] positions) { 107 auto condition = Bson.emptyObject; 108 condition["$bitsAllClear"] = positions.toBson; 109 _bson[field] = condition; 110 return cast(O)this; 111 } 112 @safe O BitsAllClear(this O)(string field, int mask) { 113 auto condition = Bson.emptyObject; 114 condition["$bitsAllClear"] = mask; 115 _bson[field] = condition; 116 return cast(O)this; 117 } 118 unittest{ 119 assert(BsonFilter.BitsAllClear("a", [1, 5]) == `{"a":{"$bitsAllClear":[1,5]}}`); 120 assert(BsonFilter.BitsAllClear("a", 35) == `{"a":{"$bitsAllClear":35}}`); 121 } 122 123 // $bitsAllSet 124 @safe O BitsAllSet(this O)(string field, BsonBinData data) { 125 auto condition = Bson.emptyObject; 126 condition["$bitsAllSet"] = data; 127 _bson[field] = condition; 128 return cast(O)this; 129 } 130 @safe O BitsAllSet(this O)(string field, int[] positions) { 131 auto condition = Bson.emptyObject; 132 condition["$bitsAllSet"] = positions.toBson; 133 _bson[field] = condition; 134 return cast(O)this; 135 } 136 @safe O BitsAllSet(this O)(string field, int mask) { 137 auto condition = Bson.emptyObject; 138 condition["$bitsAllSet"] = mask; 139 _bson[field] = condition; 140 return cast(O)this; 141 } 142 unittest{ 143 assert(BsonFilter.BitsAllSet("a", [1, 5]) == `{"a":{"$bitsAllSet":[1,5]}}`); 144 assert(BsonFilter.BitsAllSet("a", 35) == `{"a":{"$bitsAllSet":35}}`); 145 } 146 147 // $bitsAnyClear 148 @safe O BitsAnyClear(this O)(string field, BsonBinData data) { 149 auto condition = Bson.emptyObject; 150 condition["$bitsAnyClear"] = data; 151 _bson[field] = condition; 152 return cast(O)this; 153 } 154 @safe O BitsAnyClear(this O)(string field, int[] positions) { 155 auto condition = Bson.emptyObject; 156 condition["$bitsAnyClear"] = positions.toBson; 157 _bson[field] = condition; 158 return cast(O)this; 159 } 160 @safe O BitsAnyClear(this O)(string field, int mask) { 161 auto condition = Bson.emptyObject; 162 condition["$bitsAnyClear"] = mask; 163 _bson[field] = condition; 164 return cast(O)this; 165 } 166 unittest{ 167 assert(BsonFilter.BitsAnyClear("a", [1, 5]) == `{"a":{"$bitsAnyClear":[1,5]}}`); 168 assert(BsonFilter.BitsAnyClear("a", 35) == `{"a":{"$bitsAnyClear":35}}`); 169 } 170 171 // $bitsAnySet 172 @safe O BitsAnySet(this O)(string field, BsonBinData data) { 173 auto condition = Bson.emptyObject; 174 condition["$bitsAnySet"] = data; 175 _bson[field] = condition; 176 return cast(O)this; 177 } 178 @safe O BitsAnySet(this O)(string field, int[] positions) { 179 auto condition = Bson.emptyObject; 180 condition["$bitsAnySet"] = positions.toBson; 181 _bson[field] = condition; 182 return cast(O)this; 183 } 184 @safe O BitsAnySet(this O)(string field, int mask) { 185 auto condition = Bson.emptyObject; 186 condition["$bitsAnySet"] = mask; 187 _bson[field] = condition; 188 return cast(O)this; 189 } 190 unittest{ 191 assert(BsonFilter.BitsAnySet("a", [1, 5]) == `{"a":{"$bitsAnySet":[1,5]}}`); 192 assert(BsonFilter.BitsAnySet("a", 35) == `{"a":{"$bitsAnySet":35}}`); 193 } 194 195 @safe O Comment(this O)(string text) { 196 _bson["$comment"] = text; 197 return cast(O)this; 198 } 199 unittest{ 200 assert(BsonFilter.BitsAnySet("a", [1, 5]) == `{"a":{"$bitsAnySet":[1,5]}}`); 201 assert(BsonFilter.BitsAnySet("a", 35) == `{"a":{"$bitsAnySet":35}}`); 202 } 203 204 @safe O ElemMatch(this O)(string field, Bson condition) { 205 auto match = Bson.emptyObject; 206 match["$elemMatch"] = condition; 207 _bson[field] = match; 208 return cast(O)this; 209 } 210 unittest{ 211 // students: { $elemMatch: { school: 102 } } 212 } 213 214 @safe O Meta(this O)(string field, string txt) { 215 auto meta = Bson.emptyObject; 216 meta["$meta"] = Bson(text); 217 _bson[field] = meta; 218 return cast(O)this; 219 } 220 unittest{ 221 // students: { $elemMatch: { school: 102 } } 222 } 223 224 @safe O Slice(this O)(string field, int amount) { 225 auto slice = Bson.emptyObject; 226 slice["$slice"] = Bson(amount); 227 _bson[field] = slice; 228 return cast(O)this; 229 } 230 @safe O Slice(this O)(string field, size_t skip, size_t limit) { 231 auto slice = Bson.emptyObject; 232 slice["$slice"] = [skip, limit].toBson; 233 _bson[field] = slice; 234 return cast(O)this; 235 } 236 unittest{ 237 // students: { $elemMatch: { school: 102 } } 238 } 239 240 /* 241 In(this O, T)(string field, T[] values) 242 Adds an "in" filter for an array field 243 */ 244 @safe O In(this O, T)(string field, T[] values) { 245 auto condition = Bson.emptyObject; 246 condition["$in"] = values.toBson; 247 _bson[field] = condition; 248 249 return cast(O)this; 250 } 251 unittest{ 252 // In SQL: SELECT * FROM inventory WHERE status in ("A", "D") 253 assert(BsonFilter.In("status", ["A","D"]) == `{"status":{"$in":["A","D"]}}`); 254 } 255 256 /* 257 Lt(this O)(string field, string value) 258 Adds an "less than" filter for field 259 */ 260 @safe O Lt(this O, T)(string field, T value) { 261 if (_bson[field].type != Bson.Type.null_) { 262 auto condition = _bson[field]; 263 condition["$lt"] = Bson(value); 264 _bson[field] = condition; 265 } 266 else { 267 auto condition = Bson.emptyObject; 268 condition["$lt"] = Bson(value); 269 _bson[field] = condition; 270 } 271 return cast(O)this; 272 } 273 unittest{ 274 assert(BsonFilter.Lt("age", 20) == `{"age":{"$lt":20}}`); 275 assert(BsonFilter.Lt("age", 20).Gt("age", 40).Lt("name", "Tomb").Gt("name", "Raider") == `{"age":{"$lt":20,"$gt":40},"name":{"$lt":"Tomb","$gt":"Raider"}}`); 276 } 277 278 /* 279 anyLe() - Creates an less than or equal filter for an array field. 280 */ 281 @safe O Le(this O, T)(string field, string value) { 282 // TODO 283 return cast(O)this; 284 } 285 unittest{ 286 287 } 288 289 /* 290 anyNe() - Creates a not equal filter for an array field. 291 */ 292 @safe O Ne(this O, T)(string field, string value) { 293 // TODO 294 return cast(O)this; 295 } 296 unittest{ 297 298 } 299 300 /* 301 or() - creates an or field. 302 */ 303 @safe O Or(this O)(DBsonFilter[] conditions) { 304 Bson[] bsons; bsons.length = conditions.length; 305 foreach(i, condition; conditions) bsons[i] = condition.toBson; 306 return this.Or(bsons); 307 } 308 @safe O Or(this O)(Bson[] conditions) { 309 return this.Or(Bson(conditions)); 310 } 311 @safe O Or(this O)(Bson conditions) { 312 _bson["$or"] = conditions; 313 return cast(O)this; 314 } 315 unittest{ 316 // { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } 317 assert(BsonFilter.Or([BsonFilter("status", "A"), BsonFilter.Lt("qty", 30)]) == `{"$or":[{"status":"A"},{"qty":{"$lt":30}}]}`); 318 } 319 320 /* 321 Size to return documents in the collection where the array size of field is value 322 */ 323 @safe O Size(this O, T)(string field, T value) if (isIntegral!T) { 324 if (_bson[field].type != Bson.Type.null_) { 325 auto condition = _bson[field]; 326 condition["$size"] = Bson(value); 327 _bson[field] = condition; 328 } 329 else { 330 auto condition = Bson.emptyObject; 331 condition["$size"] = Bson(value); 332 _bson[field] = condition; 333 } 334 return cast(O)this; 335 } 336 unittest{ 337 writeln(BsonFilter.Size("personen", 20)); 338 assert(BsonFilter.Size("personen", 20) == `{"personen":{"$size":20}}`); 339 } 340 341 bool opEquals(string txt) { return (toString == txt); } 342 @safe Bson toBson() { 343 return _bson; 344 } 345 override string toString() { 346 return _bson.toString; 347 } 348 } 349 auto BsonFilter() { return new DBsonFilter(); } 350 auto BsonFilter(T)(string field, T value) { return new DBsonFilter(field, value); } 351 auto BsonFilter(T)(T[string] values) { return new DBsonFilter(values); } 352 353 unittest{ 354 /* writeln( 355 BsonFilter 356 .and(["field1":"b", "field2":"d"]) 357 .or(["x":"y"]));*/ 358 }