Skip to content

Commit 50b511d

Browse files
authored
fix(update/4): improve Mongo.update/4 function (#245)
* fix(update/4): improve Mongo.update/4 function - prevent endless recursion when supplied empty list - make options list optional - add more documentation + tests * doc(update/4): mention expected items for updates
1 parent bed10e2 commit 50b511d

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

lib/mongo.ex

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,29 @@ defmodule Mongo do
11291129
11301130
e.g. long-hand `query` becomes short-hand `q`, snake case `array_filters`
11311131
becomes `arrayFilters`
1132+
1133+
Example:
1134+
1135+
Mongo.update(MongoPool,
1136+
"test_collection",
1137+
query: %{foo => 4},
1138+
update: %{"$set": %{"modified_field": "new_value"}},
1139+
multi: true)
1140+
1141+
Mongo.update(MongoPool,
1142+
"test_collection",
1143+
query: %{foo: 4},
1144+
update: %{foo: 5, new_field: "new_value"}},
1145+
upsert: true)
1146+
1147+
Mongo.update(MongoPool, "test_collection", [
1148+
[q: %{foo: 24}, update: %{flag: "old"}],
1149+
[q: %{foo: 99}, update: %{luftballons: "yes"}, upsert: true]
1150+
])
11321151
"""
1152+
@spec update(GenServer.server(), collection, [Keyword.t()], Keyword.t()) :: result(Mongo.UpdateResult.t())
1153+
def update(topology_pid, coll, updates, opts \\ [])
1154+
11331155
def update(topology_pid, coll, updates, opts) do
11341156
write_concern =
11351157
filter_nils(%{
@@ -1169,12 +1191,16 @@ defmodule Mongo do
11691191
end
11701192
end
11711193

1172-
defp normalise_updates([[{_, _} | _] | _] = updates) do
1173-
updates
1174-
|> Enum.map(&normalise_update/1)
1194+
# maps list of updates (which are Keyword lists) to Mongo updates
1195+
defp normalise_updates([[{_key, _value} | _rest] | _updates] = updates) do
1196+
Enum.map(updates, &normalise_update/1)
11751197
end
11761198

1177-
defp normalise_updates(updates), do: normalise_updates([updates])
1199+
# maps a single update (= Keyword list) to Mongo update
1200+
defp normalise_updates([{_key, _value} | _rest] = updates), do: normalise_updates([updates])
1201+
1202+
# let Mongo evaluate if this is correct input
1203+
defp normalise_updates(updates), do: updates
11781204

11791205
defp normalise_update(update) do
11801206
update

test/mongo_test.exs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,24 @@ defmodule Mongo.Test do
527527
end
528528
end
529529

530+
test "update", c do
531+
coll = unique_name()
532+
533+
assert {:ok, _} = Mongo.insert_many(c.pid, coll, [%{foo: 42}, %{foo: 42}, %{_id: 1}])
534+
535+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 2, modified_count: 2, upserted_ids: []}} = Mongo.update(c.pid, coll, q: %{foo: 42}, update: %{"$set": %{foo: 0}}, multi: true)
536+
537+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 0, modified_count: 0, upserted_ids: []}} == Mongo.update(c.pid, coll, [query: %{foo: 0}, update: %{}], w: 0)
538+
539+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 0, upserted_ids: [%BSON.ObjectId{}]}} = Mongo.update(c.pid, coll, query: %{foo: 100}, update: %{foo: 24, flag: "new"}, upsert: true)
540+
541+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 2, modified_count: 1, upserted_ids: [%BSON.ObjectId{}]}} =
542+
Mongo.update(c.pid, coll, [[q: %{foo: 24}, update: %{flag: "old"}], [q: %{foo: 99}, update: %{luftballons: "yes"}, upsert: true]])
543+
544+
# message: "Write batch sizes must be between 1 and 100000. Got 0 operations."
545+
assert {:error, %Mongo.Error{code: 16}} = Mongo.update(c.pid, coll, [])
546+
end
547+
530548
# issue #19
531549
# test "correctly pass options to cursor", c do
532550
# assert %Mongo.AggregationCursor{opts: [slave_ok: true, no_cursor_timeout: true], coll: "coll"} =

0 commit comments

Comments
 (0)