Tegnap belefutottam egy érdekes problémába a MongoDB-vel kapcsolatban: egy dokumentum property-je ugybár lehet egy másik dokumentumra mutató hivatkozás is, de vajon lehet fájlokra is mutatni így linkkel? Igen! Nekem egy felhasználó profilt kell modelleznem az adatbázisban, viszont a profilképeket nem akartam inline betenni a profil infót tartalmazó dokumentumba (egyrészt a file-okat először is Base64-el encode-olni kellene, ami elég durva méretnövekedést tud okozni, másrészt pedig egy általános keresésnél, ahol nincs megadva mely mezőkre van szükségem egészen letudja lassítani a keresést).
A profil dokumentumok szerkezete így néz ki:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | { "userId":"4e5de5348deb9f622e000215", "firstName":"Gabor", "lastName":"Szabo", ..., "pictures":{ "profilePicture":{ "small": GridFS Reference, "medium": GridFS Reference, "big": GridFS Reference }, ... }, ... } |
1. lépés: szúrjuk be a GridFS-be a kívánt profilképet
1 2 3 4 5 | $m = new Mongo(); $db = $m->test_db; $profiles = $db->profiles; $gridFS = $db->getGridFS(); $gridFS->storeFile("profile_pic.jpg", array("metadata" => array("date" => new MongoDate()))); |
2. lépés: kérjük le a beszúrt objektumot (az egyszerűség kedvéért a GridFS-ben csak egy kép lesz, de természetesen a find ugyanúgy működik itt is, mint az egyéb collection-ök esetén)
1 2 3 4 5 | $m = new Mongo(); $db = $m->test_db; $profiles = $db->profiles; $gridFS = $db->getGridFS(); $picture = $gridFS->findOne(); |
3. lépés: szúrjuk be a profil dokumentumot a profiles collection-be, a lekért kép-re való hivatkozással
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $doc = array( "userId" => "4e5de5348deb9f622e000215", "firstName" => "Gabor", "lastName" => "Szabo", ... "pictures" => array( "profilePicture" => array( "small" => MongoDBRef::create($gridFS->getName(), $picture->file['_id']), "medium" => MongoDBRef::create($gridFS->getName(), $picture->file['_id']), "big" => MongoDBRef::create($gridFS->getName(), $picture->file['_id']) ) ), ... ); $profiles->insert($doc); |
4. lépés: kérjük le a profilban dokumentumban szereplő valamelyik képet (az egyszerűség kedvéért megint feltételezzük, hogy csak egy dokumentumunk van a collection-ben)
1 2 3 4 5 | $p = $profiles->findOne(); $smallProfilePicture = MongoDBRef::get($db, $p['pictures']['profilePicture']['small']); /* A fájl tényleges tartalma pedig így kapható meg */ $smallProfilePicture->getBytes(); |