Moebius.DocumentQuery
If you like your Postgres doing document goodness, then you’ll want to use this interface. Just include it in your module and you can work directly with JSONB in PostgreSQL. We’ve tried to keep reasonable parity with the Query interface, but there are some concepts here that are a bit different.
This entire module is predicated on a very particular structure for your document table. You don’t need to
create this table yourself, we’ll do it for you on save/2
if it does not exist.
If you want to create it yourself, the SQL is:
create table NAME(
id serial primary key not null,
body jsonb not null,
search tsvector,
created_at timestamptz not null default now(),
updated_at timestamptz
);
-- index the search and jsonb fields
create index idx_NAME_search on NAME using GIN(search);
create index idx_NAME on NAME using GIN(body jsonb_path_ops);
Using this structure we can apply some convention, making this interface particularly compelling. Of primary note is the Full Text search, this ability (and speed) is what sets PostgreSQL above other document systems.
Summary
Functions
This is analagous to filter
with the Query module, however this method is highly optimized for JSONB as it uses the @
(contains)
operator. This flexes the GIN index created for your table (see above)
Specifies the table or view you want to query and is an alias for the db/1
function using
a string as a table name. This is useful for specifying a table within a schema
Deletes a document based on the filter (if any)
Deletes a document with the given id
Executes a query returning a list of items
Executes a query as part of a transaction returning a list of items
Queries a table using the existence operator. Not a good query to run on a large table as it needs to do a full scan in order to match,
and can’t use the built-in index, however if you need to query embedded arrays this is a good choice. If possible, use contains/2
Queries a table using matching string criteria. Not a good query to run on a large table as it needs to do a full scan in order to match,
and can’t use the built-in index, however if you need to do a specialized query this is a good choice. If possible, use contains/2
Queries a table using matching criteria. Not a good query to run on a large table as it needs to do a full scan in order to match,
and can’t use the built-in index, however if you need to do a specialized query this is a good choice. If possible, use contains/2
Finds a document based on ID using the Primary Key index. An optimized query for finding a single document
Executes a query and returns the first matching record
Alias for Query limit
Alias for Query offset
An alias for delete/1
, removes a document based on the filter setup
An alias for delete/2
, removes a document with the specified ID
Saves a given document to the database. If an id
is present, a full UPDATE will be performed (partial updates are not possible
with JSONB), otherwise an INSERT will happen
Marks a set of fields for indexing during save
Creates a SELECT command based on the assembled pipeline
Sorts the query based on the supplied criteria
Executes a query returning a list of items
An alias for db
Functions
This is analagous to filter
with the Query module, however this method is highly optimized for JSONB as it uses the @
(contains)
operator. This flexes the GIN index created for your table (see above).
criteria: - A list of elements to look for. This list must be complete, partial matches won’t work.
Example:
db(:user_docs)
|> contains(email: "test@test.com")
|> first
Specifies the table or view you want to query and is an alias for the db/1
function using
a string as a table name. This is useful for specifying a table within a schema.
“table” - the name of the table you want to query, such as membership.user_docs
Example
result = with("membership.user_docs")
|> to_list
Queries a table using the existence operator. Not a good query to run on a large table as it needs to do a full scan in order to match,
and can’t use the built-in index, however if you need to query embedded arrays this is a good choice. If possible, use contains/2
Example:
return = db(:user_docs)
|> exists(:pets, "skippy") # :pets is an array
|> to_list
Queries a table using matching string criteria. Not a good query to run on a large table as it needs to do a full scan in order to match,
and can’t use the built-in index, however if you need to do a specialized query this is a good choice. If possible, use contains/2
Example:
return = db(:user_docs)
|> filter("body -> 'email' = $1", res.email)
|> first
Queries a table using matching criteria. Not a good query to run on a large table as it needs to do a full scan in order to match,
and can’t use the built-in index, however if you need to do a specialized query this is a good choice. If possible, use contains/2
Example:
return = db(:user_docs)
|> filter(:id, ">", 100)
|> to_list
Finds a document based on ID using the Primary Key index. An optimized query for finding a single document.
Example:
return = db(:user_docs)
|> find(12)
Executes a query and returns the first matching record
Example:
return = db(:user_docs)
|> exists(:pets, "skippy") # :pets is an array
|> sort(:city)
|> first
An alias for delete/1
, removes a document based on the filter setup.
An alias for delete/2
, removes a document with the specified ID.
Saves a given document to the database. If an id
is present, a full UPDATE will be performed (partial updates are not possible
with JSONB), otherwise an INSERT will happen.
Example:
product = %{sku: "TEST_1", name: "Test Product", description: "Just a test"}
return = db(:products)
|> save(product)
Performs a Full Text query using a full table scan. Not a good choice for larger tables. If possible,
specify your search columns on save/3
and use search/2
.
Example:
users = db(:user_docs)
|> search(for: "test.com", in: [:email])
Marks a set of fields for indexing during save.
Example:
product = %{sku: "TEST_1", name: "Test Product", description: "Just a test"}
return = db(:products)
|> searchable([:name, :description])
|> save(product)
Sorts the query based on the supplied criteria.
Example:
return = db(:user_docs)
|> exists(:pets, "skippy") # :pets is an array
|> sort(:city)
|> to_list