sql >> Databáze >  >> NoSQL >> MongoDB

Schéma pro hodnocení uživatelů – DB klíč/hodnota

Za prvé, „Slovník v uživatelské třídě“ není dobrý nápad. proč? Přidání dalšího objektu sazby vyžaduje vložení nové položky do pole, což znamená, že stará položka bude odstraněna, a toto vložení se nazývá „přesunutí dokumentu ". Přesouvání dokumentů je pomalé a MongoDB není tak skvělé, pokud jde o opětovné využití prázdného místa, takže velké přesouvání dokumentů může vést k velkým pásům prázdných datových souborů (některý text v knize 'MongoDB The Definitive Guide').

Jaké je tedy správné řešení:předpokládejme, že máte sbírku s názvem Blogy a chcete implementovat řešení hodnocení pro své blogové příspěvky a navíc sledovat každou operaci hodnocení podle uživatele.

Schéma pro blogový dokument by vypadalo takto:

{
   _id : ....,
   title: ....,
   ....
   rateCount : 0,
   rateValue : 0,
   rateAverage: 0
}

Potřebujete další kolekci (sazby) s tímto schématem dokumentu:

{
    _id: ....,
    userId: ....,
    postId:....,
    value: ..., //1 to 5
    date:....   
}

A pro to musíte definovat správný index:

db.Rates.ensureIndex({userId : 1, postId : 1})// very useful. it will result in a much faster search operation in case you want to check if a user has rated the post previously

Když chce uživatel hodnotit, musíte nejprve zkontrolovat, zda uživatel ohodnotil příspěvek nebo ne. předpokládejme, že uživatel je 'user1' , dotaz by pak byl

var ratedBefore = db.Rates.find({userId : 'user1', postId : 'post1'}).count()

A na základě ratedBefore , pokud !ratedBefore poté vložte nový dokument o sazbách do sbírky sazeb a aktualizujte stav blogu, jinak uživatel nebude moci hodnotit

if(!ratedBefore)
{
    var postId = 'post1'; // this id sould be passed before by client driver
    var userId = 'user1'; // this id sould be passed before by client driver
    var rateValue = 1; // to 5
    var rate = 
    {       
       userId: userId,
       postId: postId,
       value: rateValue,
       date:new Date()  
    };

    db.Rates.insert(rate);
    db.Blog.update({"_id" : postId}, {$inc : {'rateCount' : 1, 'rateValue' : rateValue}});
}

Co se pak stane s rateAverage ?Důrazně doporučuji vypočítat jej na základě rateCount a rateValue na straně klienta je snadné aktualizovat rateAverage s mongoquery , ale neměli byste to dělat. proč? Jednoduchá odpověď zní:Pro klienta je to velmi snadná práce zvládnout tento druh prací a uvedení průměru na každý blogový dokument vyžaduje zbytečnou aktualizaci.

průměrný dotaz by se vypočítal jako:

var blog = db.Blog.findOne({"_id" : "post1"});
var avg = blog.rateValue / blog.rateCount;
print(avg);

S tímto přístupem získáte maximální výkon s mongodb a budete mít přehled o každé sazbě podle uživatele, příspěvku a data.



  1. Odkaz na schéma Mongoose a nedefinovaný typ 'ObjectID'

  2. Je ideální, když MongoDB používá 150 MB paměti?

  3. Mongodb nemůže dotazovat poddokument podle ID (vrací hodnotu null)

  4. Použijte $lookup v poli objektů