sql >> Database teknologi >  >> NoSQL >> MongoDB

Generering af en struktur til aggregation

Da jeg havde et øjeblik til at tænke over dette, løb jeg hjem til Perl og fandt ud af dette:

use Modern::Perl;

use Moose::Autobox;
use JSON;

my $encoder = JSON->new->pretty;

my $input = [ { 4 => 10 }, { 7 => 9 }, { 90 => 7 }, { 1 => 8 } ];

my $stack = [];

foreach my $item ( reverse @{$input} ) {

  while ( my ( $key, $value ) = each %{$item} ) {
    my $rec = {
      '$cond' => [
        { '$eq' => [ '$user_id', int($key) ] },
        $value
      ]
    };

    if ( $stack->length == 0 ) {
      $rec->{'$cond'}->push( 0 );
    } else {
      my $last = $stack->pop;
      $rec->{'$cond'}->push( $last );
    }

    $stack->push( $rec );
  }

}

say $encoder->encode( $stack->[0] );

Så processen var blændende enkel.

  1. Gå gennem hvert element i arrayet og få nøglen og værdien for posten

  2. Opret et nyt "dokument", der har et array-argument til "$cond"-tasten kun to af de tre nødvendige indtastninger. Dette er de værdier, der er tildelt for at teste "$user_id" og den returnerede "vægt"-værdi.

  3. Test længden af ​​den udvendige variabel for stak , og hvis den var tom (første gang igennem), så skub værdien af ​​0 som det ses i det sidste indlejrede element til slutningen af ​​"$cond"-tasten i dokumentet.

  4. Hvis der allerede var noget der (længde> 0), så tag den værdi og skub det som den tredje værdi i "$cond"-tasten for dokumentet.

  5. Sæt det dokument tilbage som værdien af ​​stak og gentag for næste punkt

Så der er et par ting i listen, såsom at vende rækkefølgen af ​​input, som ikke er påkrævet, men producerer en naturlig rækkefølge i det indlejrede output. Mit valg til den udvendige "stack" var også et array, fordi testoperatørerne virkede enkle. Men det er virkelig kun en enestående værdi, der bliver ved med at blive genbrugt, udvidet og erstattet.

Også JSON-udskrivningen er der bare for at vise outputtet. Det eneste, der virkelig er ønsket, er den resulterende værdi af stak skal flettes ind i strukturen.

Derefter konverterede jeg logikken til rubin, ligesom det sprog, der blev brugt af OP, hvorfra jeg fik inspirationen til, hvordan man genererer denne indlejrede struktur:

require 'json'

input = [ { 4 => 10 }, { 7 => 9 }, { 90 => 7 }, { 1 => 8 } ]

stack = []

input.reverse_each {|item|

  item.each {|key,value|
    rec = {
      '$cond' => [
        { '$eq' => [ '$user_id', key ] },
        value
      ]
    }

    if ( stack.length == 0 )
      rec['$cond'].push( 0 )
    else
      last = stack.pop
      rec['$cond'].push( last )
    end

    stack.push( rec )
  }

}

puts JSON.pretty_generate(stack[0])

Og så til sidst ind i den endelige form for at generere den pipeline, som OP ønskede:

require 'json'

userWeights = [ { 4 => 10 }, { 7 => 9 }, { 90 => 7}, { 1 => 8 } ]

stack = []

userWeights.reverse_each {|item|

  item.each {|key,value|
    rec = {
      '$cond' => [
        { '$eq' => [ '$user_id', key ] },
        value
      ]
    }

    if ( stack.length == 0 )
      rec['$cond'].push( 0 )
    else
      last = stack.pop
      rec['$cond'].push( last )
    end

    stack.push( rec )
  }

}

pipeline = [
    { '$project' => {
        'user_id' => 1,
        'content' => 1,
        'date' => 1,
        'weight' => stack[0]
    }},
    { '$sort' => { 'weight' => -1, 'date' => -1 } }
]

puts JSON.pretty_generate( pipeline )

Så det var en måde at generere en struktur, der skulle overføres til aggregeret for at anvende "vægte", der er specifikke for et user_id og sorter resultaterne i samlingen.



  1. Nybegynder i realtid - Node.JS + Redis eller RabbitMQ -> klient/server hvordan?

  2. Jeg prøver at køre mongod server på ubuntu :undtagelse i initAndListen:29 Databibliotek /data/db ikke fundet., afsluttes

  3. tilpasset redis-klient kompilering mislykkes

  4. Brug af Redis til køer til flere Laravel-applikationer på en enkelt server