From 3846ddba850369dc0286ff3ac83b3a4c516807aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ton=C4=87i=20Gali=C4=87?= Date: Tue, 28 May 2024 13:24:40 +0200 Subject: [PATCH] fix(update/4): improve Mongo.update/4 function - prevent endless recursion when supplied empty list - make options list optional - add more documentation + tests --- lib/mongo.ex | 29 ++++++++++++++++++++++++++--- test/mongo_test.exs | 18 ++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/lib/mongo.ex b/lib/mongo.ex index d75ee964..68e5bbad 100644 --- a/lib/mongo.ex +++ b/lib/mongo.ex @@ -1129,7 +1129,29 @@ defmodule Mongo do e.g. long-hand `query` becomes short-hand `q`, snake case `array_filters` becomes `arrayFilters` + + Example: + + Mongo.update(MongoPool, + "test_collection", + query: %{foo => 4}, + update: %{"$set": %{"modified_field": "new_value"}}, + multi: true) + + Mongo.update(MongoPool, + "test_collection", + query: %{foo: 4}, + update: %{foo: 5, new_field: "new_value"}}, + upsert: true) + + Mongo.update(MongoPool, "test_collection", [ + [q: %{foo: 24}, update: %{flag: "old"}], + [q: %{foo: 99}, update: %{luftballons: "yes"}, upsert: true] + ]) """ + @spec update(GenServer.server(), collection, [Keyword.t()], Keyword.t()) :: result(Mongo.UpdateResult.t()) + def update(topology_pid, coll, updates, opts \\ []) + def update(topology_pid, coll, updates, opts) do write_concern = filter_nils(%{ @@ -1170,11 +1192,12 @@ defmodule Mongo do end defp normalise_updates([[{_, _} | _] | _] = updates) do - updates - |> Enum.map(&normalise_update/1) + Enum.map(updates, &normalise_update/1) end - defp normalise_updates(updates), do: normalise_updates([updates]) + defp normalise_updates([{_, _} | _] = updates), do: normalise_updates([updates]) + + defp normalise_updates(updates), do: updates defp normalise_update(update) do update diff --git a/test/mongo_test.exs b/test/mongo_test.exs index ed4d59e0..d0241fb0 100644 --- a/test/mongo_test.exs +++ b/test/mongo_test.exs @@ -527,6 +527,24 @@ defmodule Mongo.Test do end end + test "update", c do + coll = unique_name() + + assert {:ok, _} = Mongo.insert_many(c.pid, coll, [%{foo: 42}, %{foo: 42}, %{_id: 1}]) + + 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) + + 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) + + 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) + + assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 2, modified_count: 1, upserted_ids: [%BSON.ObjectId{}]}} = + Mongo.update(c.pid, coll, [[q: %{foo: 24}, update: %{flag: "old"}], [q: %{foo: 99}, update: %{luftballons: "yes"}, upsert: true]]) + + # message: "Write batch sizes must be between 1 and 100000. Got 0 operations." + assert {:error, %Mongo.Error{code: 16}} = Mongo.update(c.pid, coll, []) + end + # issue #19 # test "correctly pass options to cursor", c do # assert %Mongo.AggregationCursor{opts: [slave_ok: true, no_cursor_timeout: true], coll: "coll"} =