=encoding utf8

=head1 NAME

Couch::DB::Database - One database connection

=head1 SYNOPSIS

  my $db   = Couch::DB->db('my-db');

  # (search) documents in the database
  my @docs = $db->allDocs->docs;

=head1 DESCRIPTION

One I<node> (server) contains multiple databases.  Databases
do not contain "collections", like MongoDB: each document is
a direct child of a database.  Per database, you get multiple
files to store that data, for views, replication, and so on.
Per database, you need to set permissions.

Clustering, sharing, and replication activities on a database
are provided by the L<Couch::DB::Cluster|Couch::DB::Cluster> package.

=head1 METHODS

=head2 Constructors

=over 4

=item $class-E<gt>B<new>(%options)

B<Do not call this> method yourself, but use C<Couch::DB::db()>
to instantiate this object.

 -Option--Default
  batch   false
  couch   <required>
  name    <required>

=over 2

=item batch => BOOLEAN

When set, all write actions (which support this) to this database
will not wait for the actual update of the database.  This gives a
much higher performance, but not all errors may be reported.

=item couch => C<Couch::DB>-object

=item name => STRING

The name of a database must match C<< ^[a-z][a-z0-9_$()+/-]*$ >>.

=back

=back

=head2 Accessors

=over 4

=item $obj-E<gt>B<batch>()

Z<>

=item $obj-E<gt>B<couch>()

Z<>

=item $obj-E<gt>B<name>()

Z<>

=back

=head2 Database information

B<All CouchDB API calls> documented below, support C<%options> like C<delay>,
C<client>, and C<on_error>.  See L<Couch::DB/Using the CouchDB API>.

=over 4

=item $obj-E<gt>B<changes>(\%query, %options)

  [CouchDB API "GET /{db}/_changes", TODO]
  [CouchDB API "POST /{db}/_changes", TODO]

Feed of changes made on this database.

This very complex API call seems to be mainly used to communicate between
nodes, hence not (yet) implemented for this library.

=item $obj-E<gt>B<compactViews>(%options)

  [CouchDB API "POST /{db}/_compact"]

Instruct the database files to be compacted now.  By default, the data gets
compacted on unexpected moments.

=item $obj-E<gt>B<create>(%options)

  [CouchDB API "PUT /{db}"]

Create a new database.  The result object will have code C<HTTP_CREATED> when the
database is successfully created.  When the database already exists, it
returns C<HTTP_PRECONDITION_FAILED> and an error in the body.

Options: C<partitioned> (bool), C<q> (number of shards, default 8), and C<n> (number
of replicas, defaults to 3).

=item $obj-E<gt>B<details>(%options)

  [CouchDB API "GET /{db}"]
  [CouchDB API "GET /{db}/_partition/{partition_id}", UNTESTED]

Collect information from the database, for instance about its clustering.

 -Option   --Default
  partition  undef

=over 2

=item partition => $partition

=back

=item $obj-E<gt>B<ensureFullCommit>(%options)

  [CouchDB API "POST /{db}/_ensure_full_commit", deprecated 3.0.0]

Support for old replicators.

=item $obj-E<gt>B<exists>()

Returns a boolean, whether the database exist on the server.  This will
call L<ping()|Couch::DB::Database/"Database information"> and wait for an anwser.

=item $obj-E<gt>B<ping>(%options)

  [CouchDB API "HEAD /{db}"]

Check whether the database exists.  You may get some useful response
headers, but nothing more: the response body is empty.

=item $obj-E<gt>B<purgeDocs>(\%plan, %options)

  [CouchDB API "POST /{db}/_purge", UNTESTED]

Remove selected document revisions from the database.

A deleted document is only marked as being deleted, but exists until
purge.  There must be sufficient time between deletion and purging,
to give replication a chance to distribute the fact of deletion.

=item $obj-E<gt>B<purgeUnusedViews>(%options)

  [CouchDB API "POST /{db}/_view_cleanup", UNTESTED]

Removes view files that are not used by any design document.

=item $obj-E<gt>B<purgedRecordsLimit>(%options)

  [CouchDB API "GET /{db}/_purged_infos_limit", UNTESTED]

Returns the soft maximum number of records kept about deleting records.

=item $obj-E<gt>B<purgedRecordsLimitSet>($limit, %options)

  [CouchDB API "PUT /{db}/_purged_infos_limit", UNTESTED]

Set a new soft limit.  The default is 1000.

=item $obj-E<gt>B<remove>(%options)

  [CouchDB API "DELETE /{db}"]

Remove the database.

» example: be sure a database does not exist

Any call returns a success, which you should test; there are many reasons
why they may fail.  So, for any call, you should write like this:

  my $r = $couch->db('test')->remove;
  $r or error "Cannot remove database 'test'; $r";

However, in this case you may not want to cast an error at reply code 404
(not found). Away means away.  So, this works:

  $r && $r->code != 404 or error $r;

  use HTTP::Status  qw(HTTP_NOT_FOUND);
  $r && $r->code != HTTP_NOT_FOUND or error $r;

=item $obj-E<gt>B<revisionLimit>(%options)

  [CouchDB API "GET /{db}/_revs_limit", UNTESTED]

Returns the limit of historical revisions to store for a single document
in the database.

=item $obj-E<gt>B<revisionLimitSet>($limit, %options)

  [CouchDB API "PUT /{db}/_revs_limit", UNTESTED]

Sets the limit of historical revisions to store for a single document
in the database.  The default is 1000.

=item $obj-E<gt>B<revisionsDiff>(\%plan, %options)

  [CouchDB API "POST /{db}/_revs_diff", UNTESTED]

With given a list of document revisions, returns the document revisions
that do not exist in the database.

=item $obj-E<gt>B<revisionsMissing>(\%plan, %options)

  [CouchDB API "POST /{db}/_missing_revs", UNTESTED]

With given a list of document revisions, returns the document revisions
that do not exist in the database.

=item $obj-E<gt>B<userRoles>(%options)

  [CouchDB API "GET /{db}/_security"]

Returns the users who have access to the database, including their roles
(permissions).

Usually, it is better to simply attempt to take an action, and handle the
errors: having a role does not mean that the action will be error-less
anyway.

=item $obj-E<gt>B<userRolesChange>(%options)

  [CouchDB API "PUT /{db}/_security", UNTESTED]

Returns the users who have access to the database, including their roles
(permissions).

 -Option --Default
  admin    [ ]
  members  [ ]

=over 2

=item admin => \@names

=item members => \@names

=back

=back

=head2 Indexes

Three indexes exist:

=over 4

=item * json (Mango)

=item * text (Lucene via Cousteau, phased out)

=item * nouveau (Lucene via Nouveau, since 3.4.1)

=back

The details about each index are stored in design documents.  You may have
more than one index per design document, but any change to such document
will force a rebuild of all other indices in the same file.

=over 4

=item $obj-E<gt>B<design>( [$ddocid|$ddoc|undef] )

Returns the L<Couch::DB::Design|Couch::DB::Design> object which manages a design document.
The document will not be read until an explicit call to C<get()>.
The C<$ddocid> may start with C<_design/> which will be ignored.

=item $obj-E<gt>B<designs>( [\%search|\@%search, %options] )

  [CouchDB API "GET /{db}/_design_docs", UNTESTED]
  [CouchDB API "POST /{db}/_design_docs", UNTESTED]
  [CouchDB API "POST /{db}/_design_docs/queries", UNTESTED]

Pass one or more C<%search> queries to be run.  The default returns all designs.
The search query looks very much like a generic view search, but a few
parameters are added and missing.

If there are searches, then C<GET> is used, otherwise the C<POST> version.
The returned structure depends on the searches and the number of searches.

Rows are supported.

=item $obj-E<gt>B<indexes>(%options)

  [CouchDB API "GET /{db}/_index"]

Collect all indexes for the database.  This command supports rows.

=item $obj-E<gt>B<search>( $ddoc, $index, [\%search, %options] )

Run a search (Mango or text) on the database.  The search base is
described in the C<$index> in design document C<$ddoc>.  The design
document may be specified as id or object.

» example: search

  # Twice the same
  my $r = $db->search(myddoc => myindex => \%search);
  my $r = $db->design('myddoc')->search(myindex => \%search);

=back

=head2 Handling documents

=over 4

=item $obj-E<gt>B<allDocs>( [\%query|\@queries], %options] )

  [CouchDB API "GET /{db}/_all_docs"]
  [CouchDB API "POST /{db}/_all_docs"]
  [CouchDB API "POST /{db}/_all_docs/queries", UNTESTED]
  [CouchDB API "GET /{db}/_local_docs", UNTESTED]
  [CouchDB API "POST /{db}/_local_docs", UNTESTED]
  [CouchDB API "POST /{db}/_local_docs/queries", UNTESTED]
  [CouchDB API "GET /{db}/_partition/{partition_id}/_all_docs", UNTESTED]

Get the documents, optionally limited by a view.  If there are queries,
then C<POST> is used, otherwise the C<GET> endpoint.

The returned structure depends on the C<%query> and the number of
C<@queries> (an ARRAY of query HASHes).  This method support pagination,
but only when a single query is given.

The preferred way to use this method with a C<view>, is by calling
L<Couch::DB::Design::viewDocs()|Couch::DB::Design/"Views"> on its C<design> object.

 -Option   --Default
  design     undef
  local      false
  partition  undef
  view       undef

=over 2

=item design => $design|$ddocid

Usually called via L<Couch::DB::Design::viewDocs()|Couch::DB::Design/"Views">.

=item local => BOOLEAN

Search only in local (non-replicated) documents.  This does not support
a combination with C<partition> or C<view>.

=item partition => $name

Restrict the search to the specific partition.

=item view => $name

Restrict the search to the named view.  Requires the C<design> document.

=back

» example: getting all documents in a database

Be warned: doing it this way is memory hungry: better use paging.

  my $all  = $couch->db('users')->allDocs({include_docs => 1}, all => 1);
  my $rows = $all->page;
  my @docs = map $_->doc, @$rows;

=item $obj-E<gt>B<doc>($docid, %options)

Returns a L<Couch::DB::Document|Couch::DB::Document> for this C<$docid>.  Be aware that this
does not have any interaction with the CouchDB server.  Only when you
call actions, like C<exists()>, on that object, you can see the status and
content of the document.

All C<%options> are passed to L<Couch::DB::Database::new()|Couch::DB::Database/"Constructors">.  Of course, you do
not need to pass the C<Couch::DB::Database> object explicitly.

=item $obj-E<gt>B<find>( [\%search, %options] )

  [CouchDB API "POST /{db}/_find"]
  [CouchDB API "POST /{db}/_partition/{partition_id}/_find", UNTESTED]

Search the database for matching documents, using Mango selectors.
The documents are always included in the reply, including attachment
information.  Attachment data is not included.

The default search will select everything (uses a blank HASH as required
C<selector>).  By default, the number of results has a C<limit> of 25.
Pass C<limit> and C<skip> in C<%options> with other pagination control,
not in C<%search>.

 -Option   --Default
  partition  undef

=over 2

=item partition => $partition

=back

» example: of find() with a single query

  my $result = $couch->find or die;
  my @docs   = $result->docs;  # Couch::DB::Documents
  foreach my $doc (@docs) { ... }

=item $obj-E<gt>B<findExplain>(\%search, %options)

  [CouchDB API "POST /{db}/_explain"]
  [CouchDB API "POST /{db}/_partition/{partition_id}/_explain", UNTESTED]

Explain how the a search will be executed.

 -Option   --Default
  partition  undef

=over 2

=item partition => $partition

=back

=item $obj-E<gt>B<inspectDocs>(\@docs, %options)

  [CouchDB API "POST /{db}/_bulk_get", UNTESTED]

Return information on multiple documents at the same time.

 -Option--Default
  revs    false

=over 2

=item revs => BOOLEAN

Include the revision history of each document.

=back

=item $obj-E<gt>B<saveBulk>(\@docs, %options)

  [CouchDB API "POST /{db}/_bulk_docs"]

Insert, update, and delete multiple documents in one go.  This is more efficient
than saving them one by one.

Pass the documents which need to be save/updated in an ARRAY as first argument.

 -Option   --Default
  delete     [ ]
  issues     undef
  new_edits  true

=over 2

=item delete => $doc|\@docs

List of documents to remove.  You should not call the C<delete()> method on
them yourself!

=item issues => CODE

By default, missing reports are ignored.  When a CODE is specified, it will be called
with the result object, the failing document, and named parameters error details.
The details contain the C<error> type, the error C<reason>, and the optional
C<deleting> boolean boolean.

=item new_edits => BOOLEAN

When C<false>, than the docs will replace the existing revisions.

=back

» example: bulk adding documents

  my $doc1 = $db->doc('new1', content => $data1);
  my $doc2 = $db->doc('new2', content => $data2);
  $db->saveBulk([$doc1, $doc2]);

» example: deleting a document

Can be combined with added documents.

  my $del1 = $db->doc('victim');
  $db->saveBulk([], delete => $del1);

» example: for error handling

  sub handle($result, $doc, %details) { ... }
  $db->saveBulk(@save, issues => \&handle);

=back

=head1 DIAGNOSTICS

=over 4

=item Error: Illegal database name '$name'.

Cast by C<new()>

=item Error: need at least on document for bulk processing.

Cast by C<saveBulk()>

=item Error: need at least one document for bulk query.

Cast by C<inspectDocs()>

=back

=head1 SEE ALSO

This module is part of Couch-DB version 0.201,
built on January 30, 2026. Website: F<http://perl.overmeer.net/CPAN/>

=head1 LICENSE

For contributors see file ChangeLog.

This software is copyright (c) 2024-2026 by Mark Overmeer.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

