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

Aplikacja podobna do Twittera korzystająca z MongoDB

Masz dwa możliwe sposoby, dzięki którym użytkownik może śledzić innego użytkownika; bezpośrednio lub pośrednio przez grupę, w którym to przypadku użytkownik bezpośrednio podąża za grupą. Zacznijmy od przechowywania tych bezpośrednich relacje między użytkownikami i grupami:

{
  _id: "userA",
  followingUsers: [ "userB", "userC" ],
  followingGroups: [ "groupX", "groupY" ]
}

Teraz będziesz chciał móc szybko dowiedz się, których użytkowników śledzi użytkownik A, bezpośrednio lub pośrednio. Aby to osiągnąć, możesz zdenormalizować grupy, które obserwuje użytkownik A. Załóżmy, że grupy X i Y są zdefiniowane w następujący sposób:

{
  _id: "groupX",
  members: [ "userC", "userD" ]
},
{
  _id: "groupY",
  members: [ "userD", "userE" ]
}

Na podstawie tych grup i bezpośrednich relacji użytkownika A możesz wygenerować subskrypcje między użytkownikami. Pochodzenie subskrypcji są przechowywane z każdą subskrypcją. Dla przykładowych danych subskrypcje wyglądałyby tak:

// abusing exclamation mark to indicate a direct relation
{ ownerId: "userA", userId: "userB", origins: [ "!" ] },
{ ownerId: "userA", userId: "userC", origins: [ "!", "groupX" ] },
{ ownerId: "userA", userId: "userD", origins: [ "groupX", "groupY" ] },
{ ownerId: "userA", userId: "userE", origins: [ "groupY" ] }

Możesz łatwo wygenerować te subskrypcje, korzystając z wywołania mapy-redukuj-finalizuj dla pojedynczego użytkownika. Jeśli grupa zostanie zaktualizowana, wystarczy ponownie uruchomić redukcję mapy dla wszystkich użytkowników, którzy śledzą grupę, a subskrypcje zostaną ponownie zaktualizowane.

Redukcja mapy

Następujące funkcje redukcji mapy wygenerują subskrypcje dla jednego użytkownika.

map = function () {
  ownerId = this._id;

  this.followingUsers.forEach(function (userId) {
    emit({ ownerId: ownerId, userId: userId } , { origins: [ "!" ] });
  });

  this.followingGroups.forEach(function (groupId) {
    group = db.groups.findOne({ _id: groupId });

    group.members.forEach(function (userId) {
      emit({ ownerId: ownerId, userId: userId } , { origins: [ group._id ] });
    });
  });
}

reduce = function (key, values) {
  origins = [];

  values.forEach(function (value) {
    origins = origins.concat(value.origins);
  });

  return { origins: origins };
}

finalize = function (key, value) {
  db.subscriptions.update(key, { $set: { origins: value.origins }}, true);
}

Następnie możesz uruchomić map-reduce dla pojedynczego użytkownika, określając zapytanie, w tym przypadku dla userA .

db.users.mapReduce(map, reduce, { finalize: finalize, query: { _id: "userA" }})

Kilka uwag:

  • Powinieneś usunąć poprzednie subskrypcje użytkownika, przed uruchomieniem map-reduce dla tego użytkownika.
  • Jeśli aktualizujesz grupę, powinieneś uruchomić map-reduce dla wszystkich użytkowników, którzy obserwują grupę.

Powinienem zauważyć, że te funkcje redukcji mapy okazały się bardziej złożone niż to, o czym myślałem , ponieważ MongoDB nie obsługuje tablic jako wartości zwracanych funkcji zmniejszania. Teoretycznie funkcje mogłyby byłby znacznie prostszy, ale nie byłby kompatybilny z MongoDB. Jednak to bardziej złożone rozwiązanie może być użyte do mapowania-redukcji całych users odbiór w jednym połączeniu, jeśli kiedykolwiek będziesz musiał.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak zaktualizować istniejące dokumenty w MongoDB

  2. Filtruj tablicę za pomocą operatora $in na etapie $project

  3. Do jakiego poziomu MongoDB blokuje zapisy? (lub:co to znaczy za połączenie

  4. MongoDB Poprawny schemat dla danych zagregowanych

  5. jak skonstruować indeks złożony w mongodb