Skip to content

Commit 8ea4f3e

Browse files
committed
Add safe collection getter & merge method & insertMany
1 parent bb354a9 commit 8ea4f3e

File tree

1 file changed

+59
-20
lines changed

1 file changed

+59
-20
lines changed

source/mongoschema/package.d

+59-20
Original file line numberDiff line numberDiff line change
@@ -717,10 +717,16 @@ private:
717717
mixin template MongoSchema()
718718
{
719719
import std.typecons : Nullable;
720+
import std.range : isInputRange, ElementType;
720721

721722
static MongoCollection _schema_collection_;
722723
private BsonObjectID _schema_object_id_;
723724

725+
@property static MongoCollection collection() @safe
726+
{
727+
return _schema_collection_;
728+
}
729+
724730
/// Returns: the _id value (if set by save or find)
725731
@property ref BsonObjectID bsonID() @safe
726732
{
@@ -732,14 +738,30 @@ mixin template MongoSchema()
732738
{
733739
if (_schema_object_id_.valid)
734740
{
735-
_schema_collection_.update(Bson(["_id" : Bson(_schema_object_id_)]),
741+
collection.update(Bson(["_id" : Bson(_schema_object_id_)]),
736742
this.toSchemaBson(), UpdateFlags.upsert);
737743
}
738744
else
739745
{
740746
_schema_object_id_ = BsonObjectID.generate;
741747
auto bson = this.toSchemaBson();
742-
_schema_collection_.insert(bson);
748+
collection.insert(bson);
749+
}
750+
}
751+
752+
/// Inserts or merges into an existing value.
753+
void merge()
754+
{
755+
if (_schema_object_id_.valid)
756+
{
757+
collection.update(Bson(["_id" : Bson(_schema_object_id_)]),
758+
Bson(["$set": this.toSchemaBson()]), UpdateFlags.upsert);
759+
}
760+
else
761+
{
762+
_schema_object_id_ = BsonObjectID.generate;
763+
auto bson = this.toSchemaBson();
764+
collection.insert(bson);
743765
}
744766
}
745767

@@ -748,7 +770,7 @@ mixin template MongoSchema()
748770
{
749771
if (!_schema_object_id_.valid)
750772
return false;
751-
_schema_collection_.remove(Bson(["_id" : Bson(_schema_object_id_)]),
773+
collection.remove(Bson(["_id" : Bson(_schema_object_id_)]),
752774
DeleteFlags.SingleRemove);
753775
return true;
754776
}
@@ -757,7 +779,7 @@ mixin template MongoSchema()
757779
/// Throws: DocumentNotFoundException if not found
758780
static auto findOneOrThrow(T)(T query)
759781
{
760-
Bson found = _schema_collection_.findOne(query);
782+
Bson found = collection.findOne(query);
761783
if (found.isNull)
762784
throw new DocumentNotFoundException("Could not find one " ~ typeof(this).stringof);
763785
return found;
@@ -787,7 +809,7 @@ mixin template MongoSchema()
787809
/// Tries to find a document by the _id field and returns a Nullable which `isNull` if it could not be found. Otherwise it will be the document wrapped in the nullable.
788810
static Nullable!(typeof(this)) tryFindById(BsonObjectID id)
789811
{
790-
Bson found = _schema_collection_.findOne(Bson(["_id" : Bson(id)]));
812+
Bson found = collection.findOne(Bson(["_id" : Bson(id)]));
791813
if (found.isNull)
792814
return Nullable!(typeof(this)).init;
793815
return Nullable!(typeof(this))(fromSchemaBson!(typeof(this))(found));
@@ -802,7 +824,7 @@ mixin template MongoSchema()
802824
/// Tries to find a document in this collection. It will return a Nullable which `isNull` if the document could not be found. Otherwise it will be the document wrapped in the nullable.
803825
static Nullable!(typeof(this)) tryFindOne(T)(T query)
804826
{
805-
Bson found = _schema_collection_.findOne(query);
827+
Bson found = collection.findOne(query);
806828
if (found.isNull)
807829
return Nullable!(typeof(this)).init;
808830
return Nullable!(typeof(this))(fromSchemaBson!(typeof(this))(found));
@@ -813,7 +835,7 @@ mixin template MongoSchema()
813835
int num_skip = 0, int num_docs_per_chunk = 0)
814836
{
815837
typeof(this)[] values;
816-
foreach (entry; _schema_collection_.find(query, null, flags, num_skip, num_docs_per_chunk))
838+
foreach (entry; collection.find(query, null, flags, num_skip, num_docs_per_chunk))
817839
{
818840
values ~= fromSchemaBson!(typeof(this))(entry);
819841
}
@@ -824,7 +846,7 @@ mixin template MongoSchema()
824846
deprecated("use findAll instead") static typeof(this)[] find()
825847
{
826848
typeof(this)[] values;
827-
foreach (entry; _schema_collection_.find())
849+
foreach (entry; collection.find())
828850
{
829851
values ~= fromSchemaBson!(typeof(this))(entry);
830852
}
@@ -835,58 +857,73 @@ mixin template MongoSchema()
835857
static DocumentRange!(typeof(this)) findRange(T)(T query,
836858
QueryFlags flags = QueryFlags.None, int num_skip = 0, int num_docs_per_chunk = 0)
837859
{
838-
return DocumentRange!(typeof(this))(_schema_collection_.find(serializeToBson(query),
860+
return DocumentRange!(typeof(this))(collection.find(serializeToBson(query),
839861
null, flags, num_skip, num_docs_per_chunk));
840862
}
841863

842864
/// Queries all elements from the collection as range.
843865
static DocumentRange!(typeof(this)) findAll()
844866
{
845-
return DocumentRange!(typeof(this))(_schema_collection_.find());
867+
return DocumentRange!(typeof(this))(collection.find());
868+
}
869+
870+
/// Inserts many documents at once. The resulting IDs of the symbols will be generated by the server and not known to the caller.
871+
static void insertMany(T)(T documents, InsertFlags options = InsertFlags.none)
872+
if (isInputRange!T && is(ElementType!T : typeof(this)))
873+
{
874+
import std.array : array;
875+
import std.algorithm : map;
876+
877+
if (documents.empty)
878+
return;
879+
collection.insert(documents.map!((a) {
880+
a.bsonID = BsonObjectID.init;
881+
return a.toSchemaBson;
882+
}).array, options); // .array needed because of vibe-d issue #2185
846883
}
847884

848885
/// Updates a document.
849886
static void update(T, U)(T query, U update, UpdateFlags options = UpdateFlags.none)
850887
{
851-
_schema_collection_.update(query, update, options);
888+
collection.update(query, update, options);
852889
}
853890

854891
/// Updates a document or inserts it when not existent. Shorthand for `update(..., UpdateFlags.upsert)`
855892
static void upsert(T, U)(T query, U update, UpdateFlags options = UpdateFlags.upsert)
856893
{
857-
_schema_collection_.update(query, update, options);
894+
collection.update(query, update, options);
858895
}
859896

860897
/// Deletes one or any amount of documents matching the selector based on the flags.
861898
static void remove(T)(T selector, DeleteFlags flags = DeleteFlags.none)
862899
{
863-
_schema_collection_.remove(selector, flags);
900+
collection.remove(selector, flags);
864901
}
865902

866903
/// Removes all documents from this collection.
867904
static void removeAll()
868905
{
869-
_schema_collection_.remove();
906+
collection.remove();
870907
}
871908

872909
/// Drops the entire collection and all indices in the database.
873910
static void dropTable()
874911
{
875-
_schema_collection_.drop();
912+
collection.drop();
876913
}
877914

878915
/// Returns the count of documents in this collection matching this query.
879916
static auto count(T)(T query)
880917
{
881-
return _schema_collection_.count(query);
918+
return collection.count(query);
882919
}
883920

884921
/// Returns the count of documents in this collection.
885922
static auto countAll()
886923
{
887924
import vibe.data.bson : Bson;
888925

889-
return _schema_collection_.count(Bson.emptyObject);
926+
return collection.count(Bson.emptyObject);
890927
}
891928

892929
/// Start of an aggregation call. Returns a pipeline with typesafe functions for modifying the pipeline and running it at the end.
@@ -906,7 +943,7 @@ mixin template MongoSchema()
906943
/// --------------------
907944
static SchemaPipeline aggregate()
908945
{
909-
return SchemaPipeline(_schema_collection_);
946+
return SchemaPipeline(collection);
910947
}
911948
}
912949

@@ -917,8 +954,10 @@ void register(T)(MongoCollection collection) @safe
917954

918955
static if (hasMember!(T, "_schema_collection_"))
919956
{
920-
assert(T._schema_collection_.name.length == 0, "Can't register a Schema to 2 collections!");
921-
T._schema_collection_ = collection;
957+
(() @trusted {
958+
assert(T._schema_collection_.name.length == 0, "Can't register a Schema to 2 collections!");
959+
T._schema_collection_ = collection;
960+
})();
922961
}
923962

924963
foreach (memberName; __traits(allMembers, T))

0 commit comments

Comments
 (0)