sql >> Database >  >> NoSQL >> MongoDB

Een structuur voor aggregatie genereren

Toen ik even de tijd had om hierover na te denken, rende ik terug naar huis om perl te zoeken en werkte dit uit:

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] );

Dus het proces was verblindend eenvoudig.

  1. Doorloop elk item in de array en verkrijg de sleutel en waarde voor het item

  2. Maak een nieuw "document" met een array-argument voor de "$cond"-sleutel, slechts twee van de vereiste drie items. Dit zijn de waarden die zijn toegewezen om de "$user_id" en de geretourneerde "weight"-waarde te testen.

  3. Test de lengte van de buitenste variabele voor stack , en als het leeg was (eerste keer door) dan duwen de waarde van 0 zoals te zien in het laatste geneste element aan het einde van de "$cond"-toets in het document.

  4. Als er al iets was (lengte> 0), neem dan die waarde en duwen het als de derde waarde in de "$cond"-toets voor het document.

  5. Zet dat document terug als de waarde van stack en herhaal voor het volgende item

Er zijn dus een paar dingen in de lijst, zoals het omkeren van de volgorde van de invoer, wat niet vereist is, maar een natuurlijke volgorde produceert in de geneste uitvoer. Mijn keuze voor die externe "stack" was ook een array omdat de testoperators eenvoudig leken. Maar het is eigenlijk gewoon een unieke waarde die steeds opnieuw wordt gebruikt, aangevuld en vervangen.

Ook de JSON-afdrukken zijn er gewoon om de uitvoer te tonen. Het enige dat echt gewenst is, is de resulterende waarde van stack worden samengevoegd in de structuur.

Daarna zette ik de logica om in robijn, net als de taal die door het OP werd gebruikt, waar ik de inspiratie vandaan haalde voor het genereren van deze geneste structuur:

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])

En dan uiteindelijk in de definitieve vorm om de pijplijn te genereren die het OP wilde:

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 )

Dus dat was een manier om een ​​structuur te genereren die moet worden doorgegeven aan het aggregaat om "gewichten" toe te passen die specifiek zijn voor een user_id en sorteer de resultaten in de verzameling.



  1. Update entiteit in redis met spring-data-redis

  2. hoe je onderliggende objecten in mongodb kunt opvragen

  3. MongoDB via Mongoose JS - Wat is findByID?

  4. Hoofdletterongevoelig sorteren in MongoDB