Current section
Files
Jump to
Current section
Files
lib/mongo_find.ex
defmodule Mongo.Find do
@moduledoc """
Find operation on MongoDB
"""
use Mongo.Helpers
defstruct [
mongo: nil,
collection: nil,
selector: %{},
projector: %{},
batchSize: 0,
skip: 0,
opts: %{},
mods: %{}]
@doc """
Creates a new find operation.
Not to be used directly, prefer `Mongo.Collection.find/3`
"""
def new(collection, jsString, projector) when is_binary(jsString), do: new(collection, %{'$where': jsString}, projector)
def new(collection, selector, projector) do
%__MODULE__{collection: collection, selector: selector, projector: projector, opts: collection |> Mongo.Collection.read_opts}
end
@doc """
Sets where MongoDB begins returning results
Must be run before executing the query
iex> Mongo.connect.%@m{"test"}.collection("anycoll").find.skip(1).toArray |> Enum.count
5
iex> Mongo.connect.%@m{"test"}.collection("anycoll").find.skip(2).toArray |> Enum.count
4
"""
def skip(find, skip), do: %__MODULE__{find| skip: skip}
@doc """
Executes the query and returns a `%Mongo.Cursor{}`
"""
def exec(find) do
Mongo.Cursor.exec(find.collection, Mongo.Request.query(find), find.batchSize)
end
@doc """
Runs the explain operator that provides information on the query plan
"""
def explain(find) do
find |> addSpecial(:'$explain', 1) |> Enum.at(0)
end
@doc """
Add hint opperator that forces the query optimizer to use a specific index to fulfill the query
"""
def hint(f, hints)
def hint(f, indexName) when is_atom(indexName), do: f |> addSpecial(:'$hint', indexName)
def hint(f, hints) when is_map(hints), do: f |> addSpecial(:'$hint', hints)
@doc """
Sets query options
Defaults option set is equivalent of calling:
Find.opts(
awaitdata: false
nocursortimeout: false
slaveok: true
tailablecursor: false)
"""
def opts(find, options), do: %__MODULE__{find| opts: options}
def addSpecial(find, k, v) do
%__MODULE__{find| mods: Map.put(find.mods, k, v)}
end
defimpl Enumerable do
@doc """
Executes the query and reduce retrieved documents into a value
"""
def reduce(find, acc, reducer) do
case Mongo.Find.exec(find) do
%Mongo.Cursor{}=cursor ->
case Enumerable.reduce(cursor, {:cont, acc},
fn(response, acc)->
case Enumerable.reduce(response, acc, reducer) do
{:done, acc} -> {:cont, {:cont, acc}}
{:halted, acc} -> {:halt, acc}
{:suspended, acc} -> {:suspend, acc}
error -> {:halt, error}
end
end) do
{:done, {:cont, acc}} -> {:done, acc}
other -> other
end
error -> error
end
end
@doc """
Counts number of documents to be retreived
"""
def count(find) do
case Mongo.Collection.count(find.collection, find.selector, Map.take(find, [:skip, :limit])) do
%Mongo.Error{} -> -1
n -> n
end
end
@doc """
Not implemented
"""
def member?(_, _), do: {:error, __MODULE__}
end
end