MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Generowanie struktury do agregacji

Kiedy miałem chwilę, żeby się nad tym zastanowić, pobiegłem z powrotem do domu do perla i wymyśliłem to:

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

Proces był więc oślepiająco prosty.

  1. Przejrzyj każdy element w tablicy i uzyskaj klucz i wartość wpisu

  2. Utwórz nowy „dokument”, który ma w argumencie tablicy do klucza „$cond” tylko dwa z wymaganych trzech wpisów. Są to wartości przypisane do testowania „$user_id” i zwróconej wartości „weight”.

  3. Przetestuj długość zmiennej zewnętrznej dla stosu , a jeśli była pusta (za pierwszym razem), wciśnij wartość 0 jak widać w ostatnim zagnieżdżonym elemencie na końcu klawisza „$cond” w dokumencie.

  4. Jeśli coś już tam było (długość> 0), weź tę wartość i pchnij jest to trzecia wartość w kluczu „$cond” dokumentu.

  5. Odłóż ten dokument z powrotem jako wartość stosu i powtórz dla następnego elementu

Na liście znajduje się więc kilka rzeczy, takich jak odwrócenie kolejności danych wejściowych, co nie jest wymagane, ale tworzy naturalną kolejność w zagnieżdżonych danych wyjściowych. Ponadto moim wyborem dla tego zewnętrznego „stosu” była tablica, ponieważ operatory testu wydawały się proste. Ale tak naprawdę jest to tylko pojedyncza wartość, która jest ponownie wykorzystywana, rozszerzana i zastępowana.

Również drukowanie JSON jest tylko po to, aby pokazać dane wyjściowe. Wszystko, czego naprawdę potrzeba, to wynikowa wartość stosu do połączenia ze strukturą.

Następnie przekonwertowałem logikę na ruby, podobnie jak język używany przez OP, z którego czerpałem inspirację do generowania tej zagnieżdżonej struktury:

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

A potem w końcu do ostatecznej formy, aby wygenerować potok, którego chciał OP:

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 )

Był to więc sposób na wygenerowanie struktury, która zostanie przekazana do agregatu w celu zastosowania „wag” specyficznych dla user_id i posortuj wyniki w kolekcji.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak uzyskać dane ReferenceField w mongoengine?

  2. Wyrażenie regularne dla MongoDB ObjectID

  3. Integracja ClusterControl z SNMP:część druga

  4. Sprawdzanie wyjątkowości osadzonego dokumentu w zakresie jego rodzica w manguście

  5. Grupuj według określonego elementu tablicy z platformą agregacji mongo