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

MongoDB - Użyj struktury agregacji lub mapreduce do dopasowania tablicy ciągów w dokumentach (dopasowanie profilu)

MapReduce uruchomi JavaScript w osobnym wątku i użyje podanego kodu do emisji i zmniejszenia części dokumentu w celu agregacji w określonych polach. Z pewnością możesz spojrzeć na ćwiczenie jako agregację po każdej „wartości pola”. Framework agregacji również może to zrobić, ale byłby znacznie szybszy, ponieważ agregacja działałaby na serwerze w C++, a nie w osobnym wątku JavaScript. Ale struktura agregacji może zwrócić więcej danych niż 16 MB, w takim przypadku konieczne byłoby bardziej złożone partycjonowanie zestawu danych.

Ale wydaje się, że problem jest o wiele prostszy. Chcesz tylko znaleźć dla każdego profilu, jakie inne profile współdzielą z nim określone atrybuty - bez znajomości rozmiaru zestawu danych i wymagań dotyczących wydajności, zakładam, że masz indeks na fieldValues, więc wydajne byłoby zapytanie na nim, a następnie możesz uzyskać pożądane wyniki za pomocą tej prostej pętli:

> db.profiles.find().forEach( function(p) { 
       print("Matching profiles for "+tojson(p));
       printjson(
            db.profiles.find(
               {"fieldValues": {"$in" : p.fieldValues},  
                                "_id" : {$gt:p._id}}
            ).toArray()
       ); 
 }  );

Wyjście:

Matching profiles for {
    "_id" : 1,
    "firstName" : "John",
    "lastName" : "Smith",
    "fieldValues" : [
        "favouriteColour|red",
        "food|pizza",
        "food|chinese"
    ]
}
[
    {
        "_id" : 2,
        "firstName" : "Sarah",
        "lastName" : "Jane",
        "fieldValues" : [
            "favouriteColour|blue",
            "food|pizza",
            "food|mexican",
            "pets|yes"
        ]
    },
    {
        "_id" : 3,
        "firstName" : "Rachel",
        "lastName" : "Jones",
        "fieldValues" : [
            "food|pizza"
        ]
    }
]
Matching profiles for {
    "_id" : 2,
    "firstName" : "Sarah",
    "lastName" : "Jane",
    "fieldValues" : [
        "favouriteColour|blue",
        "food|pizza",
        "food|mexican",
        "pets|yes"
    ]
}
[
    {
        "_id" : 3,
        "firstName" : "Rachel",
        "lastName" : "Jones",
        "fieldValues" : [
            "food|pizza"
        ]
    }
]
Matching profiles for {
    "_id" : 3,
    "firstName" : "Rachel",
    "lastName" : "Jones",
    "fieldValues" : [
        "food|pizza"
    ]
}
[ ]

Oczywiście możesz dostosować zapytanie, aby nie wykluczać już dopasowanych profili (zmieniając {$gt:p._id} do {$ne:{p._id}} i inne poprawki. Ale nie jestem pewien, jaką dodatkową wartość można by uzyskać, używając struktury agregacji lub mapreduce, ponieważ tak naprawdę nie jest to agregowanie pojedynczej kolekcji na jednym z jej pól (sądząc po formacie wyświetlanych danych wyjściowych). Jeśli Twoje wymagania dotyczące formatu wyjściowego są elastyczne, z pewnością możliwe jest również skorzystanie z jednej z wbudowanych opcji agregacji.

Sprawdziłem, jak by to wyglądało, gdyby agregacja wokół poszczególnych wartości pól nie była zła, może ci pomóc, jeśli twoje dane wyjściowe będą pasować do tego:

> db.profiles.aggregate({$unwind:"$fieldValues"}, 
      {$group:{_id:"$fieldValues", 
              matchedProfiles : {$push:
               {  id:"$_id", 
                  name:{$concat:["$firstName"," ", "$lastName"]}}},
                  num:{$sum:1}
               }}, 
      {$match:{num:{$gt:1}}});
{
    "result" : [
        {
            "_id" : "food|pizza",
            "matchedProfiles" : [
                {
                    "id" : 1,
                    "name" : "John Smith"
                },
                {
                    "id" : 2,
                    "name" : "Sarah Jane"
                },
                {
                    "id" : 3,
                    "name" : "Rachel Jones"
                }
            ],
            "num" : 3
        }
    ],
    "ok" : 1
}

To w zasadzie mówi:„Dla każdego fieldValue ($unwind) grupuj według fieldValue tablicę pasujących identyfikatorów i nazw profili, licząc, ile dopasowań gromadzi każda wartość fieldValue ($group), a następnie wyklucz te, które mają tylko jeden pasujący profil.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak skonfigurować indeksy mongoDB w django-nonrel bez używania modeli?

  2. Jak uzyskać status połączenia w sterowniku C# MongoDB v2.0?

  3. Express Mongoose Model.find() zwraca undefined

  4. Jak określić kolejność właściwości w obiekcie javascript dla indeksu MongoDB w node.js?

  5. Morphia/MongoDB:Dostęp do obiektu osadzonego z obiektu @Embedded