-
Notifications
You must be signed in to change notification settings - Fork 72
Open
Description
👋
Hi there and thanks for creating the mongodb-driver! 💚
Problem
How I think I'd wanna insert new records, given a repo that can write, fails:
iex(7)> Mongo.Repo.insert(%Mongo.User{name: "Tobi-san"})
[error] Unable to send request to database because of %Mongo.Error{message: "invalid document: &Mongo.object_id/0", code: nil, host: nil, fail_command: nil, error_labels: nil, resumable: false, retryable_reads: nil, retryable_writes: nil, not_writable_primary_or_recovering: nil, error_info: nil}
{:error,
%Mongo.Error{
message: "invalid document: &Mongo.object_id/0",
code: nil,
host: nil,
fail_command: nil,
error_labels: nil,
resumable: false,
retryable_reads: nil,
retryable_writes: nil,
not_writable_primary_or_recovering: nil,
error_info: nil
}}
Context
Pretty normal schema/repo (simplified/omitted attributes):
defmodule Mongo.User do
use Mongo.Collection
collection "users" do
attribute :name, String.t()
end
end
defmodule Mongo.Repo do
use Mongo.Repo, otp_app: :my_app
end
Root Cause
I'm pretty sure this fails because per default _id
is set to said function:
iex(9)> %Mongo.User{}
%Mongo.User{
_id: &Mongo.object_id/0,
# ....
}
And the insert
code never calls it before inserting:
elixir-mongodb-driver/lib/mongo/repo.ex
Lines 68 to 76 in 91d6746
def insert(%{__struct__: module} = doc, opts \\ []) do | |
collection = module.__collection__(:collection) | |
doc = module.timestamps(doc) | |
case Mongo.insert_one(@topology, collection, module.dump(doc), opts) do | |
{:error, reason} -> {:error, reason} | |
{:ok, %{inserted_id: id}} -> {:ok, %{doc | _id: id}} | |
end | |
end |
Solution
I believe the insert
code should check if _id
stores a 0-arity function, and if so call it and replace the value of _id
with it
It may also be intentional not to insert records like this directly, but I think it'd be nice. Hence I'm looking for guidance.
Workaround
Some sort of new
function can be used as a workaround:
def new_with_id(attrs \\ %{}) do
struct!(%__MODULE__{_id: Mongo.object_id()}, attrs)
end
Metadata
Metadata
Assignees
Labels
No labels