ExSift 0.2.0 - Filter any Elixir type with MongoDB-style queries
ExSift 0.2.0 is out. The big headline: you can now filter anything not just plain maps. Keyword lists, MapSets, structs, and any custom type all work out of the box.
What’s new
Filter keyword lists
data = [[name: "Alice", age: 30], [name: "Bob", age: 25]]
ExSift.filter(data, %{"age" => %{"$gt" => 28}})
# => [[name: "Alice", age: 30]]
Filter structs directly
Shape matching, dot notation, and all operators work on any struct - no boilerplate needed:
defmodule User, do: defstruct [:name, :age, :role]
data = [
%User{name: "Alice", age: 30, role: "admin"},
%User{name: "Bob", age: 25, role: "user"},
%User{name: "Charlie", age: 35, role: "admin"}
]
ExSift.filter(data, %{role: "admin", age: %{"$gte" => 30}})
# => [%User{name: "Alice", ...}, %User{name: "Charlie", ...}]
# Dot notation through nested structs
ExSift.filter(records, %{"address.city" => "NYC"})
MapSet fields - $size, $all, $in, $elemMatch
data = [
%{user: "alice", perms: MapSet.new([:read, :write, :delete])},
%{user: "bob", perms: MapSet.new([:read])}
]
# Who has both :read and :write?
ExSift.filter(data, %{perms: %{"$all" => [:read, :write]}})
# => [%{user: "alice", ...}]
# Who has exactly 1 permission?
ExSift.filter(data, %{perms: %{"$size" => 1}})
# => [%{user: "bob", ...}]
# Who has :write in their perms?
ExSift.filter(data, %{perms: %{"$in" => [:write]}})
# => [%{user: "alice", ...}]
Custom types via the Collection protocol
Implement ExSift.Collection for any type and it will work with all operators:
defimpl ExSift.Collection, for: MyQueue do
def fetch(q, key), do: Map.get(q, key)
def to_pairs(q), do: [size: q.size, name: q.name]
def member?(q, value), do: value in q.items
def size(q), do: length(q.items)
end
# Now ExSift works on MyQueue natively
ExSift.filter(queues, %{name: "priority", "$size" => 5})
Compiled filters work across all types
compile/1 returns a plain function. Reuse it across any collection type:
is_senior = ExSift.compile(%{age: %{"$gte" => 30}})
Enum.filter(maps, is_senior)
Enum.filter(structs, is_senior)
Enum.filter(keyword_lists, is_senior)
Enum.count(all_users, is_senior)
Upgrading
No breaking changes. Drop in the new version:
{:ex_sift, "~> 0.2.0"}
Links
- Hex: ex_sift | Hex
- Docs: ex_sift v0.1.0 — Documentation
- GitHub: GitHub - sahilpohare/ex_sift: MongoDB-style query filtering for Elixir collections. · GitHub
- Changelog: ex_sift/CHANGELOG.md at main · sahilpohare/ex_sift · GitHub
As always, feedback and PRs welcome!






















