Skip to content

Commit e474f59

Browse files
committed
update_one, update_many, replace_one, replace_many now return 'upserted_ids'
1 parent 59f526c commit e474f59

File tree

4 files changed

+49
-42
lines changed

4 files changed

+49
-42
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ to implement the current requirements for the driver.
1313

1414
## Motivation
1515

16-
* Refactoring old code into new
17-
* Understand the magic in the code
18-
* Simplify code: remove raw_find (raw_find called from cursors, raw_find called with "$cmd"), so raw_find is more calling a command than a find query.
19-
* Better support for new MongoDB version, for example the ability to use views
20-
* Upgrade to DBConnection 2.x
21-
* Because the driver is used in production environments, quick adjustments are necessary.
16+
* [ ] Refactoring old code into new
17+
* [ ] Understand the magic in the code
18+
* [x] Simplify code: remove raw_find (raw_find called from cursors, raw_find called with "$cmd"), so raw_find is more calling a command than a find query.
19+
* [x] Better support for new MongoDB version, for example the ability to use views
20+
* [x] Upgrade to DBConnection 2.x
21+
* [ ] Because the driver is used in production environments, quick adjustments are necessary.
2222

2323
## Features
2424

lib/mongo.ex

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -769,25 +769,24 @@ defmodule Mongo do
769769
@doc """
770770
Update all documents matching the filter.
771771
772-
Uses MongoDB update operators to specify the updates. For more information
772+
Uses MongoDB update operators to specify the updates. For more information and all options
773773
please refer to the
774-
[MongoDB documentation](http://docs.mongodb.org/manual/reference/operator/update/)
775-
776-
## Options
774+
[MongoDB documentation](https://docs.mongodb.com/manual/reference/command/update/#dbcmd.update)
777775
778-
* `:upsert` - if set to `true` creates a new document when no document
779-
matches the filter (default: `false`)
780776
"""
781777
@spec update_many(GenServer.server, collection, BSON.document, BSON.document, Keyword.t) :: result(Mongo.UpdateResult.t)
782778
def update_many(topology_pid, coll, filter, update, opts \\ []) do
783779
_ = modifier_docs(update, :update)
784780
update_documents(topology_pid, coll, filter, update, true, opts)
785781
end
786782

783+
##
784+
# Calls the update command:
785+
#
786+
# see https://docs.mongodb.com/manual/reference/command/update/#update-command-output
787+
#
787788
defp update_documents(topology_pid, coll, filter, update, multi, opts) do
788789

789-
# see https://docs.mongodb.com/manual/reference/command/update/#update-command-output
790-
# validation of the update document
791790
write_concern = %{
792791
w: Keyword.get(opts, :w),
793792
j: Keyword.get(opts, :j),
@@ -799,7 +798,7 @@ defmodule Mongo do
799798
u: update,
800799
upsert: Keyword.get(opts, :upsert),
801800
multi: multi,
802-
collation: Keyword.get(opts, :ordered),
801+
collation: Keyword.get(opts, :collation),
803802
arrayFilters: Keyword.get(opts, :filters)
804803
} |> filter_nils()
805804

@@ -812,20 +811,33 @@ defmodule Mongo do
812811
] |> filter_nils()
813812

814813
with {:ok, conn, _, _} <- select_server(topology_pid, :write, opts),
815-
{:ok, doc} <- direct_command(conn, query, opts) do
814+
{:ok, doc} <- direct_command(conn, query, opts) do
815+
816816
case doc do
817-
# todo: better handling off the result
817+
818818
%{"writeErrors" => _} -> {:error, %Mongo.WriteError{n: doc["n"], ok: doc["ok"], write_errors: doc["writeErrors"]}}
819+
820+
%{"n" => n, "nModified" => n_modified, "upserted" => upserted} ->
821+
case Map.get(write_concern, :w) do
822+
0 -> {:ok, %Mongo.UpdateResult{acknowledged: false}}
823+
_ -> {:ok, %Mongo.UpdateResult{matched_count: n, modified_count: n_modified, upserted_ids: filter_upsert_ids(upserted)}}
824+
end
825+
819826
%{"n" => n, "nModified" => n_modified} ->
820827
case Map.get(write_concern, :w) do
821828
0 -> {:ok, %Mongo.UpdateResult{acknowledged: false}}
822829
_ -> {:ok, %Mongo.UpdateResult{matched_count: n, modified_count: n_modified}}
823830
end
824-
_ -> {:ok, nil}
831+
832+
_ -> {:ok, nil}
833+
825834
end
826835
end
827836
end
828837

838+
defp filter_upsert_ids(nil), do: []
839+
defp filter_upsert_ids(upserted), do: Enum.map(upserted, fn doc -> doc["_id"] end)
840+
829841
@doc """
830842
Similar to `update_many/5` but unwraps the result and raises on error.
831843
"""

lib/mongo/results.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ defmodule Mongo.UpdateResult do
5050
5151
* `:matched_count` - Number of matched documents
5252
* `:modified_count` - Number of modified documents
53-
* `:upserted_id` - If the operation was an upsert, the upserted id
53+
* `:upserted_ids` - If the operation was an upsert, the upserted ids
5454
"""
5555

5656
@type t :: %__MODULE__{
5757
acknowledged: boolean,
5858
matched_count: non_neg_integer,
5959
modified_count: non_neg_integer,
60-
upserted_id: nil | BSON.ObjectId.t
60+
upserted_ids: list(BSON.ObjectId.t)
6161
}
6262

63-
defstruct [acknowledged: true, matched_count: 0, modified_count: 0, upserted_id: 0]
63+
defstruct [acknowledged: true, matched_count: 0, modified_count: 0, upserted_ids: []]
6464
end

test/mongo_test.exs

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -449,16 +449,15 @@ defmodule Mongo.Test do
449449

450450
assert {:ok, _} = Mongo.insert_many(c.pid, coll, [%{foo: 42}, %{foo: 42}, %{foo: 43}])
451451

452-
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_id: 0}} = Mongo.replace_one(c.pid, coll, %{foo: 42}, %{foo: 0})
452+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_ids: []}} = Mongo.replace_one(c.pid, coll, %{foo: 42}, %{foo: 0})
453453

454454
assert [_] = Mongo.find(c.pid, coll, %{foo: 0}) |> Enum.to_list
455455
assert [_] = Mongo.find(c.pid, coll, %{foo: 42}) |> Enum.to_list
456456

457-
# todo id
458-
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 0, upserted_id: 0}} = Mongo.replace_one(c.pid, coll, %{foo: 50}, %{foo: 0}, upsert: true)
459-
# assert [_] = Mongo.find(c.pid, coll, %{_id: id}) |> Enum.to_list
457+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 0, upserted_ids: [id]}} = Mongo.replace_one(c.pid, coll, %{foo: 50}, %{foo: 0}, upsert: true)
458+
assert [_] = Mongo.find(c.pid, coll, %{_id: id}) |> Enum.to_list
460459

461-
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_id: 0}} = Mongo.replace_one(c.pid, coll, %{foo: 43}, %{foo: 1}, upsert: true)
460+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_ids: []}} = Mongo.replace_one(c.pid, coll, %{foo: 43}, %{foo: 1}, upsert: true)
462461
assert [] = Mongo.find(c.pid, coll, %{foo: 43}) |> Enum.to_list
463462
assert [_] = Mongo.find(c.pid, coll, %{foo: 1}) |> Enum.to_list
464463
end
@@ -468,7 +467,7 @@ defmodule Mongo.Test do
468467

469468
assert {:ok, _} = Mongo.insert_many(c.pid, coll, [%{foo: 42}, %{_id: 1}])
470469

471-
assert %Mongo.UpdateResult{acknowledged: true, matched_count: 0, modified_count: 0, upserted_id: 0} = Mongo.replace_one!(c.pid, coll, %{foo: 43}, %{foo: 0})
470+
assert %Mongo.UpdateResult{acknowledged: true, matched_count: 0, modified_count: 0, upserted_ids: []} = Mongo.replace_one!(c.pid, coll, %{foo: 43}, %{foo: 0})
472471

473472
assert nil == Mongo.replace_one!(c.pid, coll, %{foo: 45}, %{foo: 0}, w: 0)
474473

@@ -486,16 +485,15 @@ defmodule Mongo.Test do
486485

487486
assert {:ok, _} = Mongo.insert_many(c.pid, coll, [%{foo: 42}, %{foo: 42}, %{foo: 43}])
488487

489-
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_id: 0}} = Mongo.update_one(c.pid, coll, %{foo: 42}, %{"$set": %{foo: 0}})
488+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_ids: []}} = Mongo.update_one(c.pid, coll, %{foo: 42}, %{"$set": %{foo: 0}})
490489

491490
assert [_] = Mongo.find(c.pid, coll, %{foo: 0}) |> Enum.to_list
492491
assert [_] = Mongo.find(c.pid, coll, %{foo: 42}) |> Enum.to_list
493492

494-
# todo id
495-
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 0, upserted_id: 0}} = Mongo.update_one(c.pid, coll, %{foo: 50}, %{"$set": %{foo: 0}}, upsert: true)
496-
# todo assert [_] = Mongo.find(c.pid, coll, %{_id: id}) |> Enum.to_list
493+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 0, upserted_ids: [id]}} = Mongo.update_one(c.pid, coll, %{foo: 50}, %{"$set": %{foo: 0}}, upsert: true)
494+
assert [_] = Mongo.find(c.pid, coll, %{_id: id}) |> Enum.to_list
497495

498-
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_id: 0}} = Mongo.update_one(c.pid, coll, %{foo: 43}, %{"$set": %{foo: 1}}, upsert: true)
496+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_ids: []}} = Mongo.update_one(c.pid, coll, %{foo: 43}, %{"$set": %{foo: 1}}, upsert: true)
499497
assert [] = Mongo.find(c.pid, coll, %{foo: 43}) |> Enum.to_list
500498
assert [_] = Mongo.find(c.pid, coll, %{foo: 1}) |> Enum.to_list
501499
end
@@ -505,7 +503,7 @@ defmodule Mongo.Test do
505503

506504
assert {:ok, _} = Mongo.insert_many(c.pid, coll, [%{foo: 42}, %{_id: 1}])
507505

508-
assert %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_id: 0} = Mongo.update_one!(c.pid, coll, %{foo: 42}, %{"$set": %{foo: 0}})
506+
assert %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_ids: []} = Mongo.update_one!(c.pid, coll, %{foo: 42}, %{"$set": %{foo: 0}})
509507

510508
assert nil == Mongo.update_one!(c.pid, coll, %{foo: 42}, %{}, w: 0)
511509

@@ -517,22 +515,19 @@ defmodule Mongo.Test do
517515
test "update_many", c do
518516
coll = unique_name()
519517

520-
assert_raise ArgumentError, fn ->
521-
Mongo.update_many(c.pid, coll, %{foo: 42}, %{foo: 0})
522-
end
518+
assert_raise ArgumentError, fn -> Mongo.update_many(c.pid, coll, %{foo: 42}, %{foo: 0}) end
523519

524520
assert {:ok, _} = Mongo.insert_many(c.pid, coll, [%{foo: 42}, %{foo: 42}, %{foo: 43}])
525521

526-
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 2, modified_count: 2, upserted_id: 0}} = Mongo.update_many(c.pid, coll, %{foo: 42}, %{"$set": %{foo: 0}})
522+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 2, modified_count: 2, upserted_ids: []}} = Mongo.update_many(c.pid, coll, %{foo: 42}, %{"$set": %{foo: 0}})
527523

528524
assert [_, _] = Mongo.find(c.pid, coll, %{foo: 0}) |> Enum.to_list
529525
assert [] = Mongo.find(c.pid, coll, %{foo: 42}) |> Enum.to_list
530526

531-
# todo id
532-
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 0, upserted_id: 0}} = Mongo.update_many(c.pid, coll, %{foo: 50}, %{"$set": %{foo: 0}}, upsert: true)
533-
# assert [_] = Mongo.find(c.pid, coll, %{_id: id}) |> Enum.to_list
527+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 0, upserted_ids: [id]}} = Mongo.update_many(c.pid, coll, %{foo: 50}, %{"$set": %{foo: 0}}, upsert: true)
528+
assert [_] = Mongo.find(c.pid, coll, %{_id: id}) |> Enum.to_list
534529

535-
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_id: 0}} = Mongo.update_many(c.pid, coll, %{foo: 43}, %{"$set": %{foo: 1}}, upsert: true)
530+
assert {:ok, %Mongo.UpdateResult{acknowledged: true, matched_count: 1, modified_count: 1, upserted_ids: []}} = Mongo.update_many(c.pid, coll, %{foo: 43}, %{"$set": %{foo: 1}}, upsert: true)
536531
assert [] = Mongo.find(c.pid, coll, %{foo: 43}) |> Enum.to_list
537532
assert [_] = Mongo.find(c.pid, coll, %{foo: 1}) |> Enum.to_list
538533
end
@@ -542,7 +537,7 @@ defmodule Mongo.Test do
542537

543538
assert {:ok, _} = Mongo.insert_many(c.pid, coll, [%{foo: 42}, %{foo: 42}, %{_id: 1}])
544539

545-
assert %Mongo.UpdateResult{acknowledged: true, matched_count: 2, modified_count: 2, upserted_id: 0} = Mongo.update_many!(c.pid, coll, %{foo: 42}, %{"$set": %{foo: 0}})
540+
assert %Mongo.UpdateResult{acknowledged: true, matched_count: 2, modified_count: 2, upserted_ids: []} = Mongo.update_many!(c.pid, coll, %{foo: 42}, %{"$set": %{foo: 0}})
546541

547542
assert nil == Mongo.update_many!(c.pid, coll, %{foo: 0}, %{}, w: 0)
548543

0 commit comments

Comments
 (0)