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

use Carp 'croak';
use Mango::BSON qw(bson_code bson_doc bson_oid);
use Mango::Bulk;
use Mango::Cursor;
use Mango::Cursor::Query;

has [qw(db name)];

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

  my $command = bson_doc(aggregate => $self->name, pipeline => $pipeline,
    %{shift // {}});
  $command->{cursor} //= {} unless $command->{explain};

  # Blocking
  return $self->_aggregate($command, $self->db->command($command)) unless $cb;

  # Non-blocking
  return $self->db->command($command,
    sub { shift; $self->$cb(shift, $self->_aggregate($command, shift)) });
}

sub build_index_name { join '_', keys %{$_[1]} }

sub bulk { Mango::Bulk->new(collection => shift) }

sub create {
  my $self = shift;
  my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
  return $self->_command(bson_doc(create => $self->name, %{shift // {}}), $cb);
}

sub drop { $_[0]->_command(bson_doc(drop => $_[0]->name), $_[1]) }

sub drop_index {
  my ($self, $name) = (shift, shift);
  return $self->_command(bson_doc(dropIndexes => $self->name, index => $name),
    shift);
}

sub ensure_index {
  my ($self, $spec) = (shift, shift);
  my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
  my $doc = shift // {};

  $doc->{name} //= $self->build_index_name($spec);
  $doc->{key} = $spec;

  # Non-blocking
  my $command = bson_doc createIndexes => $self->name, indexes => [$doc];
  return $self->db->command($command => sub { shift; $self->$cb(shift) })
    if $cb;

  # Blocking
  $self->db->command($command);
}

sub find {
  Mango::Cursor::Query->new(
    collection => shift,
    query      => shift // {},
    fields     => shift // {}
  );
}

sub find_and_modify {
  my ($self, $opts) = (shift, shift);
  return $self->_command(bson_doc(findAndModify => $self->name, %$opts),
    shift, sub { shift->{value} });
}

sub find_one {
  my ($self, $query) = (shift, shift);
  $query = {_id => $query} if ref $query eq 'Mango::BSON::ObjectID';
  my $cb = ref $_[-1] eq 'CODE' ? pop : undef;

  # Non-blocking
  my $cursor = $self->find($query, @_)->limit(-1);
  return $cursor->next(sub { shift; $self->$cb(@_) }) if $cb;

  # Blocking
  return $cursor->next;
}

sub full_name { join '.', $_[0]->db->name, $_[0]->name }

sub index_information {
  my $self = shift;
  my $cb = ref $_[-1] eq 'CODE' ? pop : undef;

  my $cmd = bson_doc(listIndexes => $self->name, @_);

  $self->_command($cmd, $cb,
    sub {
      my $doc = shift or return bson_doc;
      bson_doc map { delete $_->{ns}; (delete $_->{name}, $_) }
        @{$doc->{cursor}->{firstBatch}};
    }
  );
}

sub insert {
  my ($self, $orig_docs, $cb) = @_;
  $orig_docs = [$orig_docs] unless ref $orig_docs eq 'ARRAY';

  # Make a shallow copy of the documents and add an id if needed
  my @docs = map { { %$_ } } @$orig_docs;
  my @ids = map { $_->{_id} //= bson_oid } @docs;

  my $command = bson_doc
    insert       => $self->name,<commit_msg>keep document's members order when doing an insert<commit_after>package Mango::Collection;
use Mojo::Base -base;

use Carp 'croak';
use Mango::BSON qw(bson_code bson_doc bson_oid);
use Mango::Bulk;
use Mango::Cursor;
use Mango::Cursor::Query;

has [qw(db name)];

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

  my $command = bson_doc(aggregate => $self->name, pipeline => $pipeline,
    %{shift // {}});
  $command->{cursor} //= {} unless $command->{explain};

  # Blocking
  return $self->_aggregate($command, $self->db->command($command)) unless $cb;

  # Non-blocking
  return $self->db->command($command,
    sub { shift; $self->$cb(shift, $self->_aggregate($command, shift)) });
}

sub build_index_name { join '_', keys %{$_[1]} }

sub bulk { Mango::Bulk->new(collection => shift) }

sub create {
  my $self = shift;
  my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
  return $self->_command(bson_doc(create => $self->name, %{shift // {}}), $cb);
}

sub drop { $_[0]->_command(bson_doc(drop => $_[0]->name), $_[1]) }

sub drop_index {
  my ($self, $name) = (shift, shift);
  return $self->_command(bson_doc(dropIndexes => $self->name, index => $name),
    shift);
}

sub ensure_index {
  my ($self, $spec) = (shift, shift);
  my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
  my $doc = shift // {};

  $doc->{name} //= $self->build_index_name($spec);
  $doc->{key} = $spec;

  # Non-blocking
  my $command = bson_doc createIndexes => $self->name, indexes => [$doc];
  return $self->db->command($command => sub { shift; $self->$cb(shift) })
    if $cb;

  # Blocking
  $self->db->command($command);
}

sub find {
  Mango::Cursor::Query->new(
    collection => shift,
    query      => shift // {},
    fields     => shift // {}
  );
}

sub find_and_modify {
  my ($self, $opts) = (shift, shift);
  return $self->_command(bson_doc(findAndModify => $self->name, %$opts),
    shift, sub { shift->{value} });
}

sub find_one {
  my ($self, $query) = (shift, shift);
  $query = {_id => $query} if ref $query eq 'Mango::BSON::ObjectID';
  my $cb = ref $_[-1] eq 'CODE' ? pop : undef;

  # Non-blocking
  my $cursor = $self->find($query, @_)->limit(-1);
  return $cursor->next(sub { shift; $self->$cb(@_) }) if $cb;

  # Blocking
  return $cursor->next;
}

sub full_name { join '.', $_[0]->db->name, $_[0]->name }

sub index_information {
  my $self = shift;
  my $cb = ref $_[-1] eq 'CODE' ? pop : undef;

  my $cmd = bson_doc(listIndexes => $self->name, @_);

  $self->_command($cmd, $cb,
    sub {
      my $doc = shift or return bson_doc;
      bson_doc map { delete $_->{ns}; (delete $_->{name}, $_) }
        @{$doc->{cursor}->{firstBatch}};
    }
  );
}

sub insert {
  my ($self, $orig_docs, $cb) = @_;
  $orig_docs = [$orig_docs] unless ref $orig_docs eq 'ARRAY';

  # Make a shallow copy of the documents and add an id if needed
  my @docs = map { bson_doc %$_ } @$orig_docs;
  my @ids = map { $_->{_id} //= bson_oid } @docs;

  my $command = bson_doc
    insert       => $self->name,
{'fraction_non_alphanumeric': 0.21173553719008265, 'fraction_numerical': 0.003966942148760331, 'mean_word_length': 3.4394717534849595, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 129, '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': '7623860', 'n_tokens_mistral': 2326, 'n_tokens_neox': 2278, 'n_words': 575}