diff --git a/lib/mongo.ex b/lib/mongo.ex index d75ee964..fcb2ddf3 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(%{ @@ -1169,12 +1191,16 @@ defmodule Mongo do end end - defp normalise_updates([[{_, _} | _] | _] = updates) do - updates - |> Enum.map(&normalise_update/1) + # maps list of updates (which are Keyword lists) to Mongo updates + defp normalise_updates([[{_key, _value} | _rest] | _updates] = updates) do + Enum.map(updates, &normalise_update/1) end - defp normalise_updates(updates), do: normalise_updates([updates]) + # maps a single update (= Keyword list) to Mongo update + defp normalise_updates([{_key, _value} | _rest] = updates), do: normalise_updates([updates]) + + # let Mongo evaluate if this is correct input + 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"} =