Created
July 20, 2018 16:05
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Repo do | |
use Task | |
require Logger | |
@moduledoc """ | |
It's hard to find the docs for the MongoDB adapter. Here's a direct link: | |
https://hexdocs.pm/mongodb/Mongo.html | |
""" | |
def start_link(_) do | |
Task.start(&setup/0) | |
end | |
def setup(commands \\ :all_commands) do | |
Sarlacc.Repo.Tasks.setup(commands) | |
end | |
defmacro __using__(opts \\ []) do | |
quote do | |
use Config, for: Repo | |
import ShorterMaps | |
alias Sarlacc.Repo.DB | |
@options Map.take(@config, [:pool, :name, :timeout, :pool_timeout]) |> Enum.into([]) | |
def conn, do: @options[:name] | |
def options, do: @options | |
def options(opts) do | |
Keyword.merge(@options, opts) | |
end | |
def put_timestamps(doc_or_docs, now \\ DateTime.utc_now()) | |
def put_timestamps(documents, now) when is_list(documents) do | |
Enum.map(documents, &put_timestamps(&1, now)) | |
end | |
def put_timestamps(%{} = document, now) do | |
document |> Map.put_new(:created_at, now) |> Map.put(:updated_at, now) | |
end | |
def wrap_mongo_lookup(nil), do: {:error, :no_document} | |
def wrap_mongo_lookup(document) when is_map(document) do | |
{:ok, Map.Helpers.atomize_keys(document)} | |
end | |
def wrap_mongo_lookup_all(documents) do | |
Enum.map(documents, &Map.Helpers.atomize_keys/1) | |
end | |
def command(cmds, opts \\ []) do | |
Mongo.command(conn(), cmds, options(opts)) | |
end | |
def command!(cmds, opts \\ []) do | |
Mongo.command!(conn(), cmds, options(opts)) | |
end | |
def ids(docs) do | |
Enum.map(docs, &Map.get(&1, :_id)) | |
end | |
def count(%{} = query), do: count(:default, query, []) | |
def count(%{} = query, opts), do: count(:default, query, opts) | |
def count(coll, %{} = query), do: count(coll, query, []) | |
def count(coll, %{} = query, opts) do | |
Mongo.count(conn(), collection_name(coll), query, options(opts)) | |
end | |
def aggregate(pipeline) when is_list(pipeline), do: aggregate(:default, pipeline, []) | |
def aggregate(pipeline, opts) when is_list(pipeline), do: aggregate(:default, pipeline, opts) | |
def aggregate(coll, pipeline) when is_list(pipeline), do: aggregate(coll, pipeline, []) | |
def aggregate(coll, pipeline, opts) when is_list(pipeline) do | |
Mongo.aggregate(conn(), collection_name(coll), pipeline, options(opts)) | |
|> wrap_mongo_lookup_all() | |
end | |
def find_one(%{} = query), do: find_one(:default, query, []) | |
def find_one(%{} = query, opts), do: find_one(:default, query, opts) | |
def find_one(coll, %{} = query), do: find_one(coll, query, []) | |
def find_one(coll, %{} = query, opts) do | |
Mongo.find_one(conn(), collection_name(coll), query, options(opts)) | |
|> wrap_mongo_lookup() | |
end | |
def find(%{} = query), do: find(:default, query, []) | |
def find(%{} = query, opts), do: find(:default, query, opts) | |
def find(coll, %{} = query), do: find(coll, query, []) | |
def find(coll, %{} = query, opts) do | |
Mongo.find(conn(), collection_name(coll), query, options(opts)) | |
|> wrap_mongo_lookup_all() | |
end | |
def insert_one(%{} = doc), do: insert_one(:default, doc, []) | |
def insert_one(%{} = doc, opts), do: insert_one(:default, doc, opts) | |
def insert_one(coll, %{} = doc), do: insert_one(coll, doc, []) | |
def insert_one(coll, %{} = doc, opts) when map_size(doc) != 0 do | |
Mongo.insert_one( | |
conn(), | |
collection_name(coll), | |
put_timestamps(doc), | |
options(opts) | |
) | |
end | |
def insert_one(_, _, _), do: {:error, :empty_document} | |
def insert_many(docs) when is_list(docs), do: insert_many(:default, docs, []) | |
def insert_many(docs, opts) when is_list(docs), do: insert_many(:default, docs, opts) | |
def insert_many(coll, docs) when is_list(docs), do: insert_many(coll, docs, []) | |
def insert_many(coll, docs, opts) when is_list(docs) do | |
docs = | |
docs | |
|> Enum.reject(&Enum.empty?/1) | |
|> put_timestamps() | |
Mongo.insert_many( | |
conn(), | |
collection_name(coll), | |
docs, | |
options(Keyword.merge(opts, upsert: true)) | |
) | |
end | |
def update_one(%{} = query, %{} = changeset), do: update_one(:default, query, changeset, []) | |
def update_one(%{} = query, %{} = changeset, opts), do: update_one(:default, query, changeset, opts) | |
def update_one(coll, %{} = query, %{} = changeset), do: update_one(coll, query, changeset, []) | |
def update_one(coll, %{} = query, %{} = changeset, opts) when map_size(changeset) != 0 do | |
Mongo.update_one( | |
conn(), | |
collection_name(coll), | |
query, | |
changeset, | |
options(Keyword.merge(opts, upsert: true)) | |
) | |
end | |
def update_one(_, _, _, _), do: {:error, :empty_changeset} | |
def update_many(%{} = query, %{} = changeset), do: update_many(:default, query, changeset, []) | |
def update_many(%{} = query, %{} = changeset, opts), do: update_many(:default, query, changeset, opts) | |
def update_many(coll, %{} = query, %{} = changeset), do: update_many(coll, query, changeset, []) | |
def update_many(coll, %{} = query, %{} = changeset, opts) do | |
Mongo.update_many( | |
conn(), | |
collection_name(coll), | |
query, | |
changeset, | |
options(Keyword.merge(opts, upsert: true)) | |
) | |
end | |
def upsert_one(%{} = query, %{} = doc), do: upsert_one(:default, query, doc, []) | |
def upsert_one(%{} = query, %{} = doc, opts), do: upsert_one(:default, query, doc, opts) | |
def upsert_one(coll, %{} = query, %{} = doc), do: upsert_one(coll, query, doc, []) | |
def upsert_one(coll, %{} = query, %{} = doc, opts) when map_size(doc) != 0 do | |
Mongo.replace_one( | |
conn(), | |
collection_name(coll), | |
query, | |
put_timestamps(doc), | |
options(Keyword.merge(opts, upsert: true)) | |
) | |
end | |
def upsert_one(_, _, _, _), do: {:error, :empty_document} | |
def delete_one(%{} = query), do: delete_one(:default, query, []) | |
def delete_one(%{} = query, opts), do: delete_one(:default, query, opts) | |
def delete_one(coll, %{} = query), do: delete_one(coll, query, []) | |
def delete_one(coll, %{} = query, opts) do | |
Mongo.find_one_and_delete(conn(), collection_name(coll), query, options(opts)) | |
end | |
def delete_many(%{} = query), do: delete_many(:default, query, []) | |
def delete_many(%{} = query, opts), do: delete_many(:default, query, opts) | |
def delete_many(coll, %{} = query), do: delete_many(coll, query, []) | |
def delete_many(coll, %{} = query, opts) do | |
Mongo.delete_many(conn(), collection_name(coll), query, options(opts)) | |
end | |
cond do | |
unquote(opts[:collection]) -> | |
@collection_name unquote(opts[:collection]) | |
def collection_name(:default), do: @collection_name | |
unquote(opts[:collection_suffix]) -> | |
@collection_suffix unquote(opts[:collection_suffix]) | |
def collection_name(base) | |
when is_nil(base) | |
when base == :default | |
when base == "" do | |
raise ArgumentError, message: "must specify collection base name" | |
end | |
def collection_name(base) do | |
"#{base}#{@collection_suffix}" | |
end | |
:default -> | |
def collection_name(coll), do: coll | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment