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

Czy istnieje obejście umożliwiające używanie wyrażenia regularnego w potoku agregacji Mongodb?

To pytanie wydaje się pojawiać wiele razy bez rozwiązania. Istnieją dwa możliwe rozwiązania, które znam:rozwiązanie 1- przy użyciu mapReduce. mapReduce to ogólna forma agregacji, która pozwala użytkownikowi robić wszystko, co można sobie wyobrazić i zaprogramować.

Poniżej znajduje się rozwiązanie powłoki mongo przy użyciu mapReduceRozważamy następującą kolekcję 'st'.

{ "_id" : ObjectId("51d6d23b945770d6de5883f1"), "foo" : "foo1", "bar" : "bar1" }
{ "_id" : ObjectId("51d6d249945770d6de5883f2"), "foo" : "foo2", "bar" : "bar2" }
{ "_id" : ObjectId("51d6d25d945770d6de5883f3"), "foo" : "foo2", "bar" : "bar22" }
{ "_id" : ObjectId("51d6d28b945770d6de5883f4"), "foo" : "foo2", "bar" : "bar3" }
{ "_id" : ObjectId("51d6daf6945770d6de5883f5"), "foo" : "foo3", "bar" : "bar3" }
{ "_id" : ObjectId("51d6db03945770d6de5883f6"), "foo" : "foo4", "bar" : "bar24" }

chcemy pogrupować według foo i dla każdego foo policzyć liczbę dokumentów, a także liczbę dokumentów z paskiem zawierającym podłańcuch 'bar2', czyli:

foo1: nbdoc=1, n_match = 0
foo2: nbdoc=3, n_match = 2
foo3: nbdoc=1, n_match = 0
foo4: nbdoc=1, n_match = 1

W tym celu zdefiniuj następującą funkcję mapy

var mapFunction = function() {
  var key = this.foo;
  var nb_match_bar2 = 0;
  if( this.bar.match(/bar2/g) ){
    nb_match_bar2 = 1;
  }
  var value = {
    count: 1,
    nb_match: nb_match_bar2
  };

  emit( key, value );
};

i następująca funkcja zmniejszania

var reduceFunction = function(key, values) {

  var reducedObject = {
    count: 0,
    nb_match:0
  };
  values.forEach( function(value) {
    reducedObject.count += value.count;
    reducedObject.nb_match += value.nb_match;
  }
  );
  return reducedObject;
};

uruchom mapduce i zapisz wynik w kolekcji map_reduce_result

db.st.mapReduce(mapFunction, reduceFunction, {out:'map_reduce_result'})
{
  "result" : "map_reduce_result",
  "timeMillis" : 7,
  "counts" : {
    "input" : 6,
    "emit" : 6,
    "reduce" : 1,
    "output" : 4
},
"ok" : 1,
}

Na koniec możemy zapytać o kolekcję map_reduce_result, voila! rozwiązanie

> db.map_reduce_result.find()
{ "_id" : "foo1", "value" : { "count" : 1, "nb_match" : 0 } }
{ "_id" : "foo2", "value" : { "count" : 3, "nb_match" : 2 } }
{ "_id" : "foo3", "value" : { "count" : 1, "nb_match" : 0 } }
{ "_id" : "foo4", "value" : { "count" : 1, "nb_match" : 1 } }

rozwiązanie 2- użycie dwóch oddzielnych agregacji i scalenia Nie podam szczegółów tego rozwiązania, ponieważ każdy użytkownik mongo może to łatwo zrobić. Krok 1:wykonaj agregację, ignorując część, która wymaga wyrażenia regularnego do zsumowania. na tym samym kluczu, co w kroku pierwszym.etap 1 potoku:dopasuj wyrażenie regularne;etap 2:zgrupuj według tego samego klucza co w kroku pierwszym i policz liczbę dokumentów w każdej grupie {$sum:1};krok 3:połącz wynik z kroku 1 i 2:dla każdego klucza, który pojawia się w obu wynikach, dodaj nowe pole, jeśli klucza nie ma w drugim wyniku, ustaw nowy klucz na 0.

Voila! inne rozwiązanie.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak działa przykład zliczania wiadomości w dokumentach Meteor?

  2. Uruchom migrację bazy danych (mongodb) za pomocą node.js

  3. Uzyskaj dostęp do MongoDB bezpośrednio przez JavaScript

  4. Chcesz używać bazy danych z obsługą kronikowania w 32-bitowym systemie-MongoDB

  5. Mongoose Saved _id's jako ciąg zamiast ObjectId