diff --git a/.dialyzer-ignore.exs b/.dialyzer-ignore.exs new file mode 100644 index 00000000..3c1537bf --- /dev/null +++ b/.dialyzer-ignore.exs @@ -0,0 +1,3 @@ +[ + {":0:unknown_type Unknown type: Mongo.WriteError.t/0." } +] diff --git a/lib/mongo.ex b/lib/mongo.ex index a7151bc0..f5d12a75 100644 --- a/lib/mongo.ex +++ b/lib/mongo.ex @@ -61,10 +61,12 @@ defmodule Mongo do @type conn :: DbConnection.Conn @type collection :: String.t() @opaque cursor :: Mongo.Cursor.t() | Mongo.AggregationCursor.t() + @type basic_result(t) :: {:ok, t} | {:error, Mongo.Error.t()} @type result(t) :: :ok | {:ok, t} | {:error, Mongo.Error.t()} @type write_result(t) :: - :ok | {:ok, t} | {:error, Mongo.Error.t()} | {:error, Mongo.WriteError.t()} + {:ok, t} | {:error, Mongo.Error.t()} | {:error, Mongo.WriteError.t()} @type result!(t) :: nil | t | no_return + @type basic_result!(t) :: t | no_return defmacrop bangify(result) do quote do @@ -76,6 +78,15 @@ defmodule Mongo do end end + defmacrop bangify_basic_result(basic_result) do + quote do + case unquote(basic_result) do + {:ok, value} -> value + {:error, error} -> raise error + end + end + end + @type initial_type :: :unknown | :single | :replica_set_no_primary | :sharded @doc """ @@ -167,7 +178,8 @@ defmodule Mongo do * `:max_time` - Specifies a time limit in milliseconds * `:use_cursor` - Use a cursor for a batched response (Default: true) """ - @spec aggregate(GenServer.server(), collection, [BSON.document()], Keyword.t()) :: cursor + @spec aggregate(GenServer.server(), collection, [BSON.document()], Keyword.t()) :: + {:ok, cursor} | {:error, Mongo.Error.t()} def aggregate(topology_pid, coll, pipeline, opts \\ []) do query = [ @@ -190,10 +202,10 @@ defmodule Mongo do if cursor? do query = query ++ [cursor: filter_nils(%{batchSize: opts[:batch_size]})] - aggregation_cursor(conn, "$cmd", query, nil, opts) + {:ok, aggregation_cursor(conn, "$cmd", query, nil, opts)} else query = query ++ [cursor: %{}] - aggregation_cursor(conn, "$cmd", query, nil, opts) + {:ok, aggregation_cursor(conn, "$cmd", query, nil, opts)} end end end @@ -221,7 +233,7 @@ defmodule Mongo do BSON.document(), BSON.document(), Keyword.t() - ) :: result(BSON.document()) | {:ok, nil} + ) :: basic_result(BSON.document()) | {:ok, nil} def find_one_and_update(topology_pid, coll, filter, update, opts \\ []) do _ = modifier_docs(update, :update) @@ -276,7 +288,7 @@ defmodule Mongo do BSON.document(), BSON.document(), Keyword.t() - ) :: result(BSON.document()) + ) :: basic_result(BSON.document()) def find_one_and_replace(topology_pid, coll, filter, replacement, opts \\ []) do _ = modifier_docs(replacement, :replace) @@ -320,7 +332,7 @@ defmodule Mongo do * `:collation` - Optionally specifies a collation to use in MongoDB 3.4 and higher. """ @spec find_one_and_delete(GenServer.server(), collection, BSON.document(), Keyword.t()) :: - result(BSON.document()) + basic_result(BSON.document()) def find_one_and_delete(topology_pid, coll, filter, opts \\ []) do query = filter_nils( @@ -342,7 +354,7 @@ defmodule Mongo do @doc false @spec count(GenServer.server(), collection, BSON.document(), Keyword.t()) :: - result(non_neg_integer) + basic_result(non_neg_integer) def count(topology_pid, coll, filter, opts \\ []) do query = filter_nils( @@ -363,9 +375,9 @@ defmodule Mongo do @doc false @spec count!(GenServer.server(), collection, BSON.document(), Keyword.t()) :: - result!(non_neg_integer) + basic_result!(non_neg_integer) def count!(topology_pid, coll, filter, opts \\ []) do - bangify(count(topology_pid, coll, filter, opts)) + bangify_basic_result(count(topology_pid, coll, filter, opts)) end @doc """ @@ -376,7 +388,7 @@ defmodule Mongo do * `:skip` - Number of documents to skip before returning the first """ @spec count_documents(GenServer.server(), collection, BSON.document(), Keyword.t()) :: - result(non_neg_integer) + basic_result(non_neg_integer) def count_documents(topology_pid, coll, filter, opts \\ []) do pipeline = [ @@ -388,10 +400,9 @@ defmodule Mongo do |> filter_nils |> Enum.map(&List.wrap/1) - documents = - topology_pid - |> Mongo.aggregate(coll, pipeline, opts) - |> Enum.to_list() + {:ok, cursor} = Mongo.aggregate(topology_pid, coll, pipeline, opts) + + documents = Enum.to_list(cursor) case documents do [%{"n" => count}] -> {:ok, count} @@ -403,16 +414,16 @@ defmodule Mongo do Similar to `count_documents/4` but unwraps the result and raises on error. """ @spec count_documents!(GenServer.server(), collection, BSON.document(), Keyword.t()) :: - result!(non_neg_integer) + basic_result!(non_neg_integer) def count_documents!(topology_pid, coll, filter, opts \\ []) do - bangify(count_documents(topology_pid, coll, filter, opts)) + bangify_basic_result(count_documents(topology_pid, coll, filter, opts)) end @doc """ Estimate the number of documents in a collection using collection metadata. """ @spec estimated_document_count(GenServer.server(), collection, Keyword.t()) :: - result(non_neg_integer) + basic_result(non_neg_integer) def estimated_document_count(topology_pid, coll, opts) do opts = Keyword.drop(opts, [:skip, :limit, :hint, :collation]) count(topology_pid, coll, %{}, opts) @@ -423,9 +434,9 @@ defmodule Mongo do error. """ @spec estimated_document_count!(GenServer.server(), collection, Keyword.t()) :: - result!(non_neg_integer) + basic_result!(non_neg_integer) def estimated_document_count!(topology_pid, coll, opts) do - bangify(estimated_document_count(topology_pid, coll, opts)) + bangify_basic_result(estimated_document_count(topology_pid, coll, opts)) end @doc """ @@ -437,7 +448,7 @@ defmodule Mongo do * `:collation` - Optionally specifies a collation to use in MongoDB 3.4 and """ @spec distinct(GenServer.server(), collection, String.t() | atom, BSON.document(), Keyword.t()) :: - result([BSON.t()]) + basic_result([BSON.t()]) def distinct(topology_pid, coll, field, filter, opts \\ []) do query = filter_nils( @@ -459,9 +470,9 @@ defmodule Mongo do Similar to `distinct/5` but unwraps the result and raises on error. """ @spec distinct!(GenServer.server(), collection, String.t() | atom, BSON.document(), Keyword.t()) :: - result!([BSON.t()]) + basic_result!([BSON.t()]) def distinct!(topology_pid, coll, field, filter, opts \\ []) do - bangify(distinct(topology_pid, coll, field, filter, opts)) + bangify_basic_result(distinct(topology_pid, coll, field, filter, opts)) end @doc """ @@ -482,7 +493,8 @@ defmodule Mongo do * `:projection` - Limits the fields to return for all matching document * `:skip` - The number of documents to skip before returning (Default: 0) """ - @spec find(GenServer.server(), collection, BSON.document(), Keyword.t()) :: cursor + @spec find(GenServer.server(), collection, BSON.document(), Keyword.t()) :: + cursor | {:error, Mongo.Error.t()} def find(topology_pid, coll, filter, opts \\ []) do query = [ @@ -538,7 +550,7 @@ defmodule Mongo do * `:skip` - The number of documents to skip before returning (Default: 0) """ @spec find_one(GenServer.server(), collection, BSON.document(), Keyword.t()) :: - BSON.document() | nil + BSON.document() | nil | {:error, Mongo.Error.t()} def find_one(conn, coll, filter, opts \\ []) do opts = opts @@ -597,10 +609,10 @@ defmodule Mongo do rp = ReadPreference.defaults(%{mode: :primary}) rp_opts = [read_preference: Keyword.get(opts, :read_preference, rp)] - with {:ok, conn, slave_ok, _} <- select_server(topology_pid, :read, rp_opts) do - opts = Keyword.put(opts, :slave_ok, slave_ok) - direct_command(conn, query, opts) - end + with {:ok, conn, slave_ok, _} <- select_server(topology_pid, :read, rp_opts) do + opts = Keyword.put(opts, :slave_ok, slave_ok) + direct_command(conn, query, opts) + end end @doc false @@ -699,9 +711,9 @@ defmodule Mongo do Similar to `insert_one/4` but unwraps the result and raises on error. """ @spec insert_one!(GenServer.server(), collection, BSON.document(), Keyword.t()) :: - result!(Mongo.InsertOneResult.t()) + basic_result!(Mongo.InsertOneResult.t()) def insert_one!(topology_pid, coll, doc, opts \\ []) do - bangify(insert_one(topology_pid, coll, doc, opts)) + bangify_basic_result(insert_one(topology_pid, coll, doc, opts)) end @doc """ @@ -767,9 +779,9 @@ defmodule Mongo do Similar to `insert_many/4` but unwraps the result and raises on error. """ @spec insert_many!(GenServer.server(), collection, [BSON.document()], Keyword.t()) :: - result!(Mongo.InsertManyResult.t()) + basic_result!(Mongo.InsertManyResult.t()) def insert_many!(topology_pid, coll, docs, opts \\ []) do - bangify(insert_many(topology_pid, coll, docs, opts)) + bangify_basic_result(insert_many(topology_pid, coll, docs, opts)) end @doc """ @@ -785,9 +797,9 @@ defmodule Mongo do Similar to `delete_one/4` but unwraps the result and raises on error. """ @spec delete_one!(GenServer.server(), collection, BSON.document(), Keyword.t()) :: - result!(Mongo.DeleteResult.t()) + basic_result!(Mongo.DeleteResult.t()) def delete_one!(topology_pid, coll, filter, opts \\ []) do - bangify(delete_one(topology_pid, coll, filter, opts)) + bangify_basic_result(delete_one(topology_pid, coll, filter, opts)) end @doc """ @@ -803,9 +815,9 @@ defmodule Mongo do Similar to `delete_many/4` but unwraps the result and raises on error. """ @spec delete_many!(GenServer.server(), collection, BSON.document(), Keyword.t()) :: - result!(Mongo.DeleteResult.t()) + basic_result!(Mongo.DeleteResult.t()) def delete_many!(topology_pid, coll, filter, opts \\ []) do - bangify(delete_many(topology_pid, coll, filter, opts)) + bangify_basic_result(delete_many(topology_pid, coll, filter, opts)) end defp do_delete(topology_pid, coll, filter, limit, opts) do @@ -871,9 +883,9 @@ defmodule Mongo do BSON.document(), BSON.document(), Keyword.t() - ) :: result!(Mongo.UpdateResult.t()) + ) :: basic_result!(Mongo.UpdateResult.t()) def replace_one!(topology_pid, coll, filter, replacement, opts \\ []) do - bangify(replace_one(topology_pid, coll, filter, replacement, opts)) + bangify_basic_result(replace_one(topology_pid, coll, filter, replacement, opts)) end @doc """ @@ -907,9 +919,9 @@ defmodule Mongo do Similar to `update_one/5` but unwraps the result and raises on error. """ @spec update_one!(GenServer.server(), collection, BSON.document(), BSON.document(), Keyword.t()) :: - result!(Mongo.UpdateResult.t()) + basic_result!(Mongo.UpdateResult.t()) def update_one!(topology_pid, coll, filter, update, opts \\ []) do - bangify(update_one(topology_pid, coll, filter, update, opts)) + bangify_basic_result(update_one(topology_pid, coll, filter, update, opts)) end @doc """ @@ -941,9 +953,9 @@ defmodule Mongo do BSON.document(), BSON.document(), Keyword.t() - ) :: result!(Mongo.UpdateResult.t()) + ) :: basic_result!(Mongo.UpdateResult.t()) def update_many!(topology_pid, coll, filter, update, opts \\ []) do - bangify(update_many(topology_pid, coll, filter, update, opts)) + bangify_basic_result(update_many(topology_pid, coll, filter, update, opts)) end defp do_update(topology_pid, coll, filter, update, multi, opts) do @@ -1001,26 +1013,34 @@ defmodule Mongo do @doc """ Returns a cursor to enumerate all indexes """ - @spec list_indexes(GenServer.server(), String.t(), Keyword.t()) :: cursor + @spec list_indexes(GenServer.server(), String.t(), Keyword.t()) :: + {:ok, cursor} | {:error, Mongo.Error.t()} def list_indexes(topology_pid, coll, opts \\ []) do with {:ok, conn, _, _} <- select_server(topology_pid, :read, opts) do - aggregation_cursor(conn, "$cmd", [listIndexes: coll], nil, opts) + {:ok, aggregation_cursor(conn, "$cmd", [listIndexes: coll], nil, opts)} end end @doc """ Convenient function that returns a cursor with the names of the indexes. """ - @spec list_index_names(GenServer.server(), String.t(), Keyword.t()) :: %Stream{} + @spec list_index_names(GenServer.server(), String.t(), Keyword.t()) :: + %Stream{} | {:error, Mongo.Error.t()} def list_index_names(topology_pid, coll, opts \\ []) do - list_indexes(topology_pid, coll, opts) - |> Stream.map(fn %{"name" => name} -> name end) + case list_indexes(topology_pid, coll, opts) do + {:ok, colls} -> + Stream.map(colls, fn %{"name" => name} -> name end) + + error = {:error, _} -> + error + end end @doc """ Getting Collection Names """ - @spec show_collections(GenServer.server(), Keyword.t()) :: cursor + @spec show_collections(GenServer.server(), Keyword.t()) :: + {:ok, cursor} | {:error, Mongo.Error.t()} def show_collections(topology_pid, opts \\ []) do ## # from the specs @@ -1028,10 +1048,14 @@ defmodule Mongo do # # In versions 2.8.0-rc3 and later, the listCollections command returns a cursor! # + with {:ok, conn, _, _} <- select_server(topology_pid, :read, opts) do - aggregation_cursor(conn, "$cmd", [listCollections: 1], nil, opts) - |> Stream.filter(fn coll -> coll["type"] == "collection" end) - |> Stream.map(fn coll -> coll["name"] end) + cursor = + aggregation_cursor(conn, "$cmd", [listCollections: 1], nil, opts) + |> Stream.filter(fn coll -> coll["type"] == "collection" end) + |> Stream.map(fn coll -> coll["name"] end) + + {:ok, cursor} end end @@ -1095,7 +1119,8 @@ defmodule Mongo do select_servers(topology_pid, type, opts, start_time) {:error, :selection_timeout} -> - {:error, %Mongo.Error{type: :network, message: "Topology selection timeout", code: 89}} + {:error, + %Mongo.Error{type: :network, message: "Topology selection timeout", code: 89}} end else {:ok, servers, slave_ok, mongos?} diff --git a/lib/mongo/grid_fs/bucket.ex b/lib/mongo/grid_fs/bucket.ex index 9b5c8dd7..4403c5e3 100644 --- a/lib/mongo/grid_fs/bucket.ex +++ b/lib/mongo/grid_fs/bucket.ex @@ -72,31 +72,30 @@ defmodule Mongo.GridFs.Bucket do Given a `id`, delete this stored file’s files collection document and associated chunks from a GridFS bucket. """ - @spec delete(Bucket.t(), String.t()) :: {:ok, %Mongo.DeleteResult{}} + @spec delete(Bucket.t(), String.t()) :: {:ok, %Mongo.DeleteResult{}} | {:error, Mongo.Error.t()} def delete(%Bucket{} = bucket, file_id) when is_binary(file_id) do delete(bucket, ObjectId.decode!(file_id)) end - @spec delete(Bucket.t(), BSON.ObjectId.t()) :: {:ok, %Mongo.DeleteResult{}} + @spec delete(Bucket.t(), BSON.ObjectId.t()) :: + {:ok, %Mongo.DeleteResult{}} | {:error, Mongo.Error.t()} def delete(%Bucket{topology_pid: topology_pid, opts: opts} = bucket, %BSON.ObjectId{} = oid) do - # first delete files document - collection = files_collection_name(bucket) - - {:ok, %Mongo.DeleteResult{deleted_count: _}} = - Mongo.delete_one(topology_pid, collection, %{_id: oid}, opts) - - # then delete all chunk documents - collection = chunks_collection_name(bucket) - - {:ok, %Mongo.DeleteResult{deleted_count: _}} = - Mongo.delete_many(topology_pid, collection, %{files_id: oid}, opts) + with collection <- files_collection_name(bucket), + # first delete files document + {:ok, %Mongo.DeleteResult{deleted_count: _}} <- + Mongo.delete_one(topology_pid, collection, %{_id: oid}, opts), + # then delete all chunk documents + collection <- chunks_collection_name(bucket), + {:ok, %Mongo.DeleteResult{deleted_count: del_count}} <- + Mongo.delete_many(topology_pid, collection, %{files_id: oid}, opts), + do: {:ok, %Mongo.DeleteResult{deleted_count: del_count}} end @doc """ Drops the files and chunks collections associated with this bucket. """ - @spec drop(Bucket.t()) :: Mongo.result(BSON.document()) + @spec drop(Bucket.t()) :: Mongo.basic_result(BSON.document()) def drop(%Bucket{topology_pid: topology_pid, opts: opts} = bucket) do {:ok, _} = Mongo.command(topology_pid, %{drop: files_collection_name(bucket)}, opts) {:ok, _} = Mongo.command(topology_pid, %{drop: chunks_collection_name(bucket)}, opts) @@ -105,7 +104,8 @@ defmodule Mongo.GridFs.Bucket do @doc """ Returns a cursor from the fs.files collection. """ - @spec find(Bucket.t(), BSON.document(), Keyword.t()) :: Mongo.cursor() + @spec find(Bucket.t(), BSON.document(), Keyword.t()) :: + Mongo.cursor() | {:error, Mongo.Error.t()} def find(%Bucket{topology_pid: topology_pid} = bucket, filter, opts \\ []) do Mongo.find(topology_pid, files_collection_name(bucket), filter, opts) end @@ -178,9 +178,9 @@ defmodule Mongo.GridFs.Bucket do # returns true if the collection contains a index with the given name defp index_member?(topology_pid, coll, index, opts) do - topology_pid - |> Mongo.list_indexes(coll, opts) - |> Enum.member?(index) + {:ok, cursor} = Mongo.list_indexes(topology_pid, coll, opts) + + Enum.member?(cursor, index) end ## diff --git a/lib/mongo/session.ex b/lib/mongo/session.ex index 178bdcdc..6c83055e 100644 --- a/lib/mongo/session.ex +++ b/lib/mongo/session.ex @@ -339,9 +339,10 @@ defmodule Mongo.Session do @impl :gen_statem # Abort all pending transactions if there any and end session itself. def terminate(_reason, state, %{pid: pid} = data) do - if state == :in_transaction do - _ = try_run_txn_command(data, :abortTransaction) - end + _ = + if state == :in_transaction do + try_run_txn_command(data, :abortTransaction) + end query = %{ endSessions: [data.id] diff --git a/mix.exs b/mix.exs index 718d7dd2..ed2374f8 100644 --- a/mix.exs +++ b/mix.exs @@ -15,6 +15,7 @@ defmodule Mongodb.Mixfile do description: description(), package: package(), dialyzer: [ + ignore_warnings: ".dialyzer-ignore.exs", flags: [:underspecs, :unknown, :unmatched_returns], plt_add_apps: [:logger, :connection, :db_connection, :mix, :elixir, :ssl, :public_key], plt_add_deps: :transitive diff --git a/test/mongo_test.exs b/test/mongo_test.exs index 8c5cbe6a..5153897b 100644 --- a/test/mongo_test.exs +++ b/test/mongo_test.exs @@ -44,9 +44,10 @@ defmodule Mongo.Test do cmd = [createIndexes: coll_2, indexes: [[key: [foo: 1, bar: 1], name: "not-a-collection"]]] assert {:ok, _} = Mongo.command(c.pid, cmd) + assert {:ok, colls0} = Mongo.show_collections(c.pid) + colls = - c.pid - |> Mongo.show_collections() + colls0 |> Enum.to_list() assert Enum.member?(colls, coll_1) @@ -87,8 +88,10 @@ defmodule Mongo.Test do assert {:ok, _} = Mongo.insert_one(c.pid, coll, %{foo: 44}) assert {:ok, _} = Mongo.insert_one(c.pid, coll, %{foo: 45}) + assert {:ok, colls0} = Mongo.aggregate(c.pid, coll, []) + assert [%{"foo" => 42}, %{"foo" => 43}, %{"foo" => 44}, %{"foo" => 45}] = - c.pid |> Mongo.aggregate(coll, []) |> Enum.to_list() + Enum.to_list(colls0) query = [ %{ @@ -104,27 +107,44 @@ defmodule Mongo.Test do } ] - assert [%{"_id" => "foo", "total" => 89}] = - c.pid |> Mongo.aggregate(coll, query) |> Enum.to_list() + assert {:ok, colls1} = Mongo.aggregate(c.pid, coll, query) + assert [%{"_id" => "foo", "total" => 89}] == Enum.to_list(colls1) + + assert {:ok, colls2} = Mongo.aggregate(c.pid, coll, []) + assert [] == Enum.take(colls2, 0) + + assert {:ok, colls3} = Mongo.aggregate(c.pid, coll, []) + assert [] == Enum.drop(colls3, 4) + + assert {:ok, colls4} = Mongo.aggregate(c.pid, coll, []) + assert [%{"foo" => 42}] == Enum.take(colls4, 1) + + assert {:ok, colls5} = Mongo.aggregate(c.pid, coll, []) + assert [%{"foo" => 45}] == Enum.drop(colls5, 3) + + assert {:ok, colls6} = Mongo.aggregate(c.pid, coll, [], use_cursor: false) + assert [] == Enum.take(colls6, 0) + + assert {:ok, colls7} = Mongo.aggregate(c.pid, coll, [], use_cursor: false) + assert [] == Enum.drop(colls7, 4) + + assert {:ok, colls8} = Mongo.aggregate(c.pid, coll, [], use_cursor: false) + assert [%{"foo" => 42}] = Enum.take(colls8, 1) - assert [] = c.pid |> Mongo.aggregate(coll, []) |> Enum.take(0) - assert [] = c.pid |> Mongo.aggregate(coll, []) |> Enum.drop(4) - assert [%{"foo" => 42}] = c.pid |> Mongo.aggregate(coll, []) |> Enum.take(1) - assert [%{"foo" => 45}] = c.pid |> Mongo.aggregate(coll, []) |> Enum.drop(3) + assert {:ok, colls9} = Mongo.aggregate(c.pid, coll, [], use_cursor: false) + assert [%{"foo" => 45}] == Enum.drop(colls9, 3) - assert [] = Mongo.aggregate(c.pid, coll, [], use_cursor: false) |> Enum.take(0) - assert [] = Mongo.aggregate(c.pid, coll, [], use_cursor: false) |> Enum.drop(4) + assert {:ok, colls10} = Mongo.aggregate(c.pid, coll, [], batch_size: 1) + assert [] == Enum.take(colls10, 0) - assert [%{"foo" => 42}] = - c.pid |> Mongo.aggregate(coll, [], use_cursor: false) |> Enum.take(1) + assert {:ok, colls11} = Mongo.aggregate(c.pid, coll, [], batch_size: 1) + assert [] == Enum.drop(colls11, 4) - assert [%{"foo" => 45}] = - c.pid |> Mongo.aggregate(coll, [], use_cursor: false) |> Enum.drop(3) + assert {:ok, colls12} = Mongo.aggregate(c.pid, coll, [], batch_size: 1) + assert [%{"foo" => 42}] == Enum.take(colls12, 1) - assert [] = Mongo.aggregate(c.pid, coll, [], batch_size: 1) |> Enum.take(0) - assert [] = Mongo.aggregate(c.pid, coll, [], batch_size: 1) |> Enum.drop(4) - assert [%{"foo" => 42}] = c.pid |> Mongo.aggregate(coll, [], batch_size: 1) |> Enum.take(1) - assert [%{"foo" => 45}] = c.pid |> Mongo.aggregate(coll, [], batch_size: 1) |> Enum.drop(3) + assert {:ok, colls13} = Mongo.aggregate(c.pid, coll, [], batch_size: 1) + assert [%{"foo" => 45}] == Enum.drop(colls13, 3) end test "count", c do diff --git a/test/support/specifications/crud/helpers.ex b/test/support/specifications/crud/helpers.ex index d1194974..8abfd812 100644 --- a/test/support/specifications/crud/helpers.ex +++ b/test/support/specifications/crud/helpers.ex @@ -68,7 +68,9 @@ defmodule Mongo.Specification.CRUD.Helpers do |> Map.drop(["pipeline"]) |> atomize_keys() - pid |> Mongo.aggregate(collection, pipeline, opts) |> Enum.to_list() + {:ok, cursor} = pid |> Mongo.aggregate(collection, pipeline, opts) + + Enum.to_list(cursor) end def match_operation_result?(expected, actual) do