<commit_before>package Mango::Database;
use Mojo::Base -base;

use Carp 'croak';
use Mango::BSON qw(bson_code bson_doc);
use Mango::Collection;
use Mango::GridFS;

has [qw(mango name)];

sub collection {
  my ($self, $name) = @_;
  return Mango::Collection->new(db => $self, name => $name);
}

sub collection_names {
  my ($self, $cb) = @_;

  my $len        = length $self->name;
  my $collection = $self->collection('system.namespaces');

  # Non-blocking
  return $collection->find->all(
    sub {
      my ($cursor, $err, $docs) = @_;
      $self->$cb($err, [map { substr $_->{name}, $len + 1 } @$docs]);
    }
  ) if $cb;

  # Blocking
  my $docs = $collection->find->all;
  return [map { substr $_->{name}, $len + 1 } @$docs];
}

sub command {
  my ($self, $command) = (shift, shift);
  my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
  $command = ref $command ? $command : bson_doc($command => 1, @_);

  # Non-blocking
  my $collection = $self->collection('$cmd');
  my $protocol   = $self->mango->protocol;
  return $collection->find_one(
    $command => sub {
      my ($collection, $err, $doc) = @_;
      $err ||= $protocol->command_error({docs => [$doc]});
      $self->$cb($err, $doc // {});
    }
  ) if $cb;

  # Blocking
  my $doc = $collection->find_one($command);
  if (my $err = $protocol->command_error({docs => [$doc]})) { croak $err }
  return $doc;
}

sub gridfs { Mango::GridFS->new(db => shift) }

sub stats { shift->command(bson_doc(dbstats => 1), @_) }

1;

=encoding utf8

=head1 NAME

Mango::Database - MongoDB database

=head1 SYNOPSIS

  use Mango::Database;

  my $db = Mango::Database->new(mango => $mango);
  my $collection = $db->collection('foo');
  my $gridfs     = $db->gridfs;

=head1 DESCRIPTION

L<Mango::Database> is a container for MongoDB databases used by L<Mango>.

=head1 ATTRIBUTES

L<Mango::Database> implements the following attributes.

=head2 mango

  my $mango = $db->mango;
  $db       = $db->mango(Mango->new);

L<Mango> object this database belongs to. Note that this reference is usually
weakened, so the L<Mango> object needs to be referenced elsewhere too.

=head2 name

  my $name = $db->name;
  $db      = $db->name('bar');

Name of this database.

=head1 METHODS

L<Mango::Database> inherits all methods from L<Mojo::Base> and implements the
following new ones.

=head2 collection<commit_msg>documentation tweak<commit_after>package Mango::Database;
use Mojo::Base -base;

use Carp 'croak';
use Mango::BSON qw(bson_code bson_doc);
use Mango::Collection;
use Mango::GridFS;

has [qw(mango name)];

sub collection {
  my ($self, $name) = @_;
  return Mango::Collection->new(db => $self, name => $name);
}

sub collection_names {
  my ($self, $cb) = @_;

  my $len        = length $self->name;
  my $collection = $self->collection('system.namespaces');

  # Non-blocking
  return $collection->find->all(
    sub {
      my ($cursor, $err, $docs) = @_;
      $self->$cb($err, [map { substr $_->{name}, $len + 1 } @$docs]);
    }
  ) if $cb;

  # Blocking
  my $docs = $collection->find->all;
  return [map { substr $_->{name}, $len + 1 } @$docs];
}

sub command {
  my ($self, $command) = (shift, shift);
  my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
  $command = ref $command ? $command : bson_doc($command => 1, @_);

  # Non-blocking
  my $collection = $self->collection('$cmd');
  my $protocol   = $self->mango->protocol;
  return $collection->find_one(
    $command => sub {
      my ($collection, $err, $doc) = @_;
      $err ||= $protocol->command_error({docs => [$doc]});
      $self->$cb($err, $doc // {});
    }
  ) if $cb;

  # Blocking
  my $doc = $collection->find_one($command);
  if (my $err = $protocol->command_error({docs => [$doc]})) { croak $err }
  return $doc;
}

sub gridfs { Mango::GridFS->new(db => shift) }

sub stats { shift->command(bson_doc(dbstats => 1), @_) }

1;

=encoding utf8

=head1 NAME

Mango::Database - MongoDB database

=head1 SYNOPSIS

  use Mango::Database;

  my $db = Mango::Database->new(mango => $mango);
  my $collection = $db->collection('foo');
  my $gridfs     = $db->gridfs;

=head1 DESCRIPTION

L<Mango::Database> is a container for MongoDB databases used by L<Mango>.

=head1 ATTRIBUTES

L<Mango::Database> implements the following attributes.

=head2 mango

  my $mango = $db->mango;
  $db       = $db->mango(Mango->new);

L<Mango> object this database belongs to. Note that this reference is usually
weakened, so the L<Mango> object needs to be referenced elsewhere as well.

=head2 name

  my $name = $db->name;
  $db      = $db->name('bar');

Name of this database.

=head1 METHODS

L<Mango::Database> inherits all methods from L<Mojo::Base> and implements the
following new ones.

=head2 collection
{'fraction_non_alphanumeric': 0.17776834959694526, 'fraction_numerical': 0.006364022061943148, 'mean_word_length': 3.6270853778213934, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 91, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4473007', 'n_tokens_mistral': 1753, 'n_tokens_neox': 1692, 'n_words': 463}