MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

MongoDB - Използвайте рамка за агрегиране или mapreduce за съвпадение на масив от низове в документи (съвпадение на профили)

MapReduce ще стартира JavaScript в отделна нишка и ще използва кода, който предоставяте, за да излъчи и намали части от вашия документ, за да ги агрегира в определени полета. Със сигурност можете да разглеждате упражнението като агрегиране на всяка "fieldValue". Рамката за агрегиране също може да направи това, но ще бъде много по-бързо, тъй като агрегацията ще се изпълнява на сървъра в C++, а не в отделна JavaScript нишка. Но рамката за агрегиране може да върне повече данни обратно от 16 MB, в който случай ще трябва да направите по-сложно разделяне на набора от данни.

Но изглежда, че проблемът е много по-прост от това. Просто искате да намерите за всеки профил какви други профили споделят определени атрибути с него - без да знам размера на вашия набор от данни и вашите изисквания за производителност, ще приема, че имате индекс на fieldValues, така че би било ефективно да правите заявки върху него и след това можете да получите желаните резултати с този прост цикъл:

> 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()
       ); 
 }  );

Изход:

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"
    ]
}
[ ]

Очевидно можете да промените заявката, за да не изключвате вече съвпадащи профили (като промените {$gt:p._id} към {$ne:{p._id}} и други настройки. Но не съм сигурен каква допълнителна стойност бихте получили от използването на рамка за агрегиране или mapreduce, тъй като това всъщност не е агрегиране на една колекция в едно от полетата (съдейки по формата на изхода, който показвате). Ако вашите изисквания за изходен формат са гъвкави, със сигурност е възможно да използвате и една от вградените опции за агрегиране.

Проверих, за да видя как би изглеждало това, ако се агрегира около отделни fieldValues ​​и не е лошо, може да ви помогне, ако изходът ви може да съответства на това:

> 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
}

Това основно казва „За всяка fieldValue ($unwind) група по fieldValue масив от съвпадащи _ids и имена на профили, като се брои колко съвпадения натрупва всяка fieldValue ($group) и след това се изключват тези, които имат само един съответстващ профил.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Вмъкнете масив, където елементът не съществува, иначе го актуализирайте (с множество условия)

  2. NodeJS + Mongo:Вмъкнете, ако не съществува, в противен случай - актуализирайте

  3. docker-compose MongoDB Грешка:мрежова грешка при опит за изпълнение на командата 'isMaster' на хост

  4. NodeJS Express Dependency Injection и връзки към бази данни

  5. Mongodb, linq драйвер. Как да конструирате Съдържа с променлива или изрази