Current section

Files

Jump to
gleam_mongo src mongo@crud.erl
Raw

src/mongo@crud.erl

-module(mongo@crud).
-compile(no_auto_import).
-export([insert_one/2, find_by_id/2, find_one/3, find_many/3, find_all/2, update_one/4, update_many/4, delete_one/2, delete_many/2, count_all/1, count/2, insert_many/2]).
-export_type([insert_result/0, update_result/0]).
-type insert_result() :: {insert_result, integer(), list(bson@types:value())}.
-type update_result() :: {update_result, integer(), integer()} |
{upsert_result, integer(), bson@types:value()}.
-spec insert_one(mongo@client:collection(), bson@types:value()) -> {ok,
bson@types:value()} |
{error, mongo@utils:mongo_error()}.
insert_one(Collection, Doc) ->
case begin
_pipe = Collection,
insert_many(_pipe, [Doc])
end of
{ok, {insert_result, _@1, [Id]}} ->
{ok, Id};
{error, Error} ->
{error, Error}
end.
-spec find_by_id(mongo@client:collection(), binary()) -> {ok,
bson@types:value()} |
{error, mongo@utils:mongo_error()}.
find_by_id(Collection, Id) ->
case bson@object_id:from_string(Id) of
{ok, Id@1} ->
_pipe = Collection,
find_one(
_pipe,
{document, [{<<"_id"/utf8>>, {object_id, Id@1}}]},
{document, []}
);
{error, nil} ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end.
-spec find_one(
mongo@client:collection(),
bson@types:value(),
bson@types:value()
) -> {ok, bson@types:value()} | {error, mongo@utils:mongo_error()}.
find_one(Collection, Filter, Projection) ->
case Filter of
{document, _@1} ->
case Projection of
{document, Doc} ->
Options = case Doc of
[] ->
[{limit, 1}];
_@2 ->
[{limit, 1}, {projection, Projection}]
end,
case begin
_pipe = Collection,
find_many(_pipe, Filter, Options)
end of
{ok, []} ->
{ok, null};
{ok, [Doc@1]} ->
{ok, Doc@1};
{error, Error} ->
{error, Error}
end;
_@3 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end;
_@4 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end.
-spec find_many(
mongo@client:collection(),
bson@types:value(),
list(mongo@utils:find_option())
) -> {ok, list(bson@types:value())} | {error, mongo@utils:mongo_error()}.
find_many(Collection, Filter, Options) ->
_pipe = Collection,
find(_pipe, Filter, Options).
-spec find_all(mongo@client:collection(), list(mongo@utils:find_option())) -> {ok,
list(bson@types:value())} |
{error, mongo@utils:mongo_error()}.
find_all(Collection, Options) ->
_pipe = Collection,
find(_pipe, {document, []}, Options).
-spec update_one(
mongo@client:collection(),
bson@types:value(),
bson@types:value(),
list(mongo@utils:update_option())
) -> {ok, update_result()} | {error, mongo@utils:mongo_error()}.
update_one(Collection, Filter, Change, Options) ->
_pipe = Collection,
update(_pipe, Filter, Change, Options, false).
-spec update_many(
mongo@client:collection(),
bson@types:value(),
bson@types:value(),
list(mongo@utils:update_option())
) -> {ok, update_result()} | {error, mongo@utils:mongo_error()}.
update_many(Collection, Filter, Change, Options) ->
_pipe = Collection,
update(_pipe, Filter, Change, Options, true).
-spec delete_one(mongo@client:collection(), bson@types:value()) -> {ok,
integer()} |
{error, mongo@utils:mongo_error()}.
delete_one(Collection, Filter) ->
_pipe = Collection,
delete(_pipe, Filter, false).
-spec delete_many(mongo@client:collection(), bson@types:value()) -> {ok,
integer()} |
{error, mongo@utils:mongo_error()}.
delete_many(Collection, Filter) ->
_pipe = Collection,
delete(_pipe, Filter, true).
-spec count_all(mongo@client:collection()) -> {ok, integer()} |
{error, mongo@utils:mongo_error()}.
count_all(Collection) ->
case begin
_pipe = Collection,
mongo@client:execute(
_pipe,
{document,
[{<<"count"/utf8>>, {str, erlang:element(3, Collection)}}]}
)
end of
{ok, [{<<"n"/utf8>>, {integer, N}}, {<<"ok"/utf8>>, Ok}]} ->
case Ok of
{double, 1.0} ->
{ok, N};
_@1 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end;
{error, {Code, Msg}} ->
{error, {mongo_error, Code, Msg, null}}
end.
-spec count(mongo@client:collection(), bson@types:value()) -> {ok, integer()} |
{error, mongo@utils:mongo_error()}.
count(Collection, Filter) ->
case Filter of
{document, _@1} ->
case begin
_pipe = Collection,
mongo@client:execute(
_pipe,
{document,
[{<<"count"/utf8>>,
{str, erlang:element(3, Collection)}},
{<<"query"/utf8>>, Filter}]}
)
end of
{ok, [{<<"n"/utf8>>, {integer, N}}, {<<"ok"/utf8>>, Ok}]} ->
case Ok of
{double, 1.0} ->
{ok, N};
_@2 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end;
{error, {Code, Msg}} ->
{error, {mongo_error, Code, Msg, null}}
end;
_@3 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end.
-spec insert_many(mongo@client:collection(), list(bson@types:value())) -> {ok,
insert_result()} |
{error, mongo@utils:mongo_error()}.
insert_many(Collection, Docs) ->
case gleam@list:all(Docs, fun(Doc) -> case Doc of
{document, _@1} ->
true;
_@2 ->
false
end end) of
true ->
Docs@1 = gleam@list:map(Docs, fun(D) -> case D of
{document, Fields} ->
case gleam@list:find(
Fields,
fun(Kv) ->
gleam@pair:first(Kv)
=:= <<"_id"/utf8>>
end
) of
{ok, _@3} ->
D;
{error, nil} ->
Id = bson@object_id:new(),
Fields@1 = gleam@list:prepend(
Fields,
{<<"_id"/utf8>>, {object_id, Id}}
),
{document, Fields@1}
end;
_@4 ->
D
end end),
Inserted_ids = gleam@list:map(Docs@1, fun(D@1) -> case D@1 of
{document, Fields@2} ->
case gleam@list:find(
Fields@2,
fun(Kv@1) ->
gleam@pair:first(Kv@1)
=:= <<"_id"/utf8>>
end
) of
{ok, {_@5, Id@1}} ->
Id@1;
_@6 ->
{str, <<""/utf8>>}
end;
_@7 ->
{str, <<""/utf8>>}
end end),
case begin
_pipe = Collection,
mongo@client:execute(
_pipe,
{document,
[{<<"insert"/utf8>>,
{str, erlang:element(3, Collection)}},
{<<"documents"/utf8>>, {array, Docs@1}}]}
)
end of
{ok, [{<<"n"/utf8>>, {integer, N}}, {<<"ok"/utf8>>, Ok}]} ->
case Ok of
{double, 1.0} ->
{ok, {insert_result, N, Inserted_ids}};
_@8 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end;
{ok,
[{<<"n"/utf8>>, _@9},
{<<"writeErrors"/utf8>>, {array, Errors}},
{<<"ok"/utf8>>, Ok@1}]} ->
case Ok@1 of
{double, 1.0} ->
{ok, Error@1} = case gleam@list:first(Errors) of
{ok, Error} -> {ok, Error};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"mongo/crud"/utf8>>,
function => <<"insert_many"/utf8>>,
line => 211})
end,
case Error@1 of
{document,
[{<<"index"/utf8>>, _@10},
{<<"code"/utf8>>, {integer, Code}},
{<<"keyPattern"/utf8>>, _@11},
{<<"keyValue"/utf8>>, Source},
{<<"errmsg"/utf8>>, {str, Msg}}]} ->
{error, {mongo_error, Code, Msg, Source}};
_@12 ->
{error,
{mongo_error, -16, <<""/utf8>>, null}}
end;
_@13 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end;
{error, {Code@1, Msg@1}} ->
{error, {mongo_error, Code@1, Msg@1, null}}
end;
false ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end.
-spec find(
mongo@client:collection(),
bson@types:value(),
list(mongo@utils:find_option())
) -> {ok, list(bson@types:value())} | {error, mongo@utils:mongo_error()}.
find(Collection, Filter, Options) ->
case Filter of
{document, Doc} ->
Body = case Doc of
[] ->
[{<<"find"/utf8>>, {str, erlang:element(3, Collection)}}];
_@1 ->
[{<<"find"/utf8>>, {str, erlang:element(3, Collection)}},
{<<"filter"/utf8>>, Filter}]
end,
Options@1 = gleam@list:fold(
Options,
[],
fun(Acc, Opt) -> case Opt of
{sort, {document, Sort}} ->
[{<<"sort"/utf8>>, {document, Sort}} | Acc];
{projection, {document, Projection}} ->
[{<<"projection"/utf8>>, {document, Projection}} |
Acc];
{skip, Skip} ->
[{<<"skip"/utf8>>, {integer, Skip}} | Acc];
{limit, Limit} ->
[{<<"limit"/utf8>>, {integer, Limit}} | Acc]
end end
),
Body@1 = gleam@list:append(Body, Options@1),
case begin
_pipe = Collection,
mongo@client:execute(_pipe, {document, Body@1})
end of
{ok, Result} ->
[{<<"cursor"/utf8>>, {document, Result@1}},
{<<"ok"/utf8>>, Ok}] = Result,
[{<<"firstBatch"/utf8>>, {array, Docs}},
{<<"id"/utf8>>, _@2},
{<<"ns"/utf8>>, _@3}] = Result@1,
case Ok of
{double, 1.0} ->
{ok, Docs};
_@4 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end;
{error, {Code, Msg}} ->
{error, {mongo_error, Code, Msg, null}}
end;
_@5 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end.
-spec update(
mongo@client:collection(),
bson@types:value(),
bson@types:value(),
list(mongo@utils:update_option()),
boolean()
) -> {ok, update_result()} | {error, mongo@utils:mongo_error()}.
update(Collection, Filter, Change, Options, Multi) ->
case Filter of
{document, _@1} ->
case Change of
{document, _@2} ->
Update = [{<<"q"/utf8>>, Filter},
{<<"u"/utf8>>, Change},
{<<"multi"/utf8>>, {boolean, Multi}}],
Options@1 = gleam@list:fold(
Options,
[],
fun(Acc, Opt) -> case Opt of
upsert ->
[{<<"upsert"/utf8>>, {boolean, true}} | Acc];
{array_filters, Filters} ->
[{<<"arrayFilters"/utf8>>, {array, Filters}} |
Acc]
end end
),
Update@1 = {document, gleam@list:append(Update, Options@1)},
case begin
_pipe = Collection,
mongo@client:execute(
_pipe,
{document,
[{<<"update"/utf8>>,
{str, erlang:element(3, Collection)}},
{<<"updates"/utf8>>, {array, [Update@1]}}]}
)
end of
{ok,
[{<<"n"/utf8>>, {integer, N}},
{<<"nModified"/utf8>>, {integer, Modified}},
{<<"ok"/utf8>>, Ok}]} ->
case Ok of
{double, 1.0} ->
{ok, {update_result, N, Modified}};
_@3 ->
{error,
{mongo_error, -16, <<""/utf8>>, null}}
end;
{ok,
[{<<"n"/utf8>>, {integer, N@1}},
{<<"upserted"/utf8>>,
{array,
[{document,
[{<<"index"/utf8>>, _@4},
{<<"_id"/utf8>>, Upserted}]}]}},
{<<"nModified"/utf8>>, _@5},
{<<"ok"/utf8>>, Ok@1}]} ->
case Ok@1 of
{double, 1.0} ->
{ok, {upsert_result, N@1, Upserted}};
_@6 ->
{error,
{mongo_error, -16, <<""/utf8>>, null}}
end;
{ok,
[{<<"n"/utf8>>, _@7},
{<<"writeErrors"/utf8>>, {array, Errors}},
{<<"nModified"/utf8>>, _@8},
{<<"ok"/utf8>>, Ok@2}]} ->
case Ok@2 of
{double, 1.0} ->
{ok, Error@1} = case gleam@list:first(
Errors
) of
{ok, Error} -> {ok, Error};
_try ->
erlang:error(
#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"mongo/crud"/utf8>>,
function => <<"update"/utf8>>,
line => 356}
)
end,
case Error@1 of
{document,
[{<<"index"/utf8>>, _@9},
{<<"code"/utf8>>,
{integer, Code}},
{<<"keyPattern"/utf8>>, _@10},
{<<"keyValue"/utf8>>, Source},
{<<"errmsg"/utf8>>, {str, Msg}}]} ->
{error,
{mongo_error, Code, Msg, Source}};
_@11 ->
{error,
{mongo_error,
-16,
<<""/utf8>>,
null}}
end;
_@12 ->
{error,
{mongo_error, -16, <<""/utf8>>, null}}
end;
{error, {Code@1, Msg@1}} ->
{error, {mongo_error, Code@1, Msg@1, null}}
end;
_@13 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end;
_@14 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end.
-spec delete(mongo@client:collection(), bson@types:value(), boolean()) -> {ok,
integer()} |
{error, mongo@utils:mongo_error()}.
delete(Collection, Filter, Multi) ->
case Filter of
{document, _@1} ->
case begin
_pipe = Collection,
mongo@client:execute(
_pipe,
{document,
[{<<"delete"/utf8>>,
{str, erlang:element(3, Collection)}},
{<<"deletes"/utf8>>,
{array,
[{document,
[{<<"q"/utf8>>, Filter},
{<<"limit"/utf8>>,
{integer, case Multi of
true ->
0;
false ->
1
end}}]}]}}]}
)
end of
{ok, [{<<"n"/utf8>>, {integer, N}}, {<<"ok"/utf8>>, Ok}]} ->
case Ok of
{double, 1.0} ->
{ok, N};
_@2 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end;
{ok,
[{<<"n"/utf8>>, _@3},
{<<"writeErrors"/utf8>>, {array, Errors}},
{<<"ok"/utf8>>, Ok@1}]} ->
case Ok@1 of
{double, 1.0} ->
{ok, Error@1} = case gleam@list:first(Errors) of
{ok, Error} -> {ok, Error};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"mongo/crud"/utf8>>,
function => <<"delete"/utf8>>,
line => 412})
end,
case Error@1 of
{document,
[{<<"index"/utf8>>, _@4},
{<<"code"/utf8>>, {integer, Code}},
{<<"keyPattern"/utf8>>, _@5},
{<<"keyValue"/utf8>>, Source},
{<<"errmsg"/utf8>>, {str, Msg}}]} ->
{error, {mongo_error, Code, Msg, Source}};
_@6 ->
{error,
{mongo_error, -16, <<""/utf8>>, null}}
end;
_@7 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end;
{error, {Code@1, Msg@1}} ->
{error, {mongo_error, Code@1, Msg@1, null}}
end;
_@8 ->
{error, {mongo_error, -16, <<""/utf8>>, null}}
end.