sql >> Databasteknik >  >> NoSQL >> MongoDB

Schema för användarbetyg - Nyckel/Värde DB

För det första är "Ordbok i användarklass" ingen bra idé. Varför? Att lägga till extra satsobjekt kräver att ett nytt objekt skjuts till arrayen, vilket innebär att det gamla objektet kommer att tas bort, och denna infogning kallas "flytta ett dokument ". Flytta dokument går långsamt och MongoDB är inte så bra på att återanvända tomt utrymme, så att flytta runt dokument kan resultera i stora delar av tomma datafiler (viss text i boken 'MongoDB The Definitive Guide').

Vad är då den korrekta lösningen:anta att du har en samling som heter Bloggar och vill implementera en betygslösning för dina blogginlägg, och dessutom hålla reda på varje användarbaserad prisoperation.

Schemat för ett bloggdokument skulle vara så här:

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

Du behöver en annan samling (priser) med detta dokumentschema:

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

Och du måste definiera ett korrekt index för det:

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

När en användare vill betygsätta måste du först kontrollera om användaren har betygsatt inlägget eller inte. anta att användaren är 'user1' , då skulle frågan vara

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

Och baserat på ratedBefore , om !ratedBefore infoga sedan ett nytt prisdokument i Prisinsamling och uppdatera bloggstatus, annars får användaren inte betygsätta

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

Vad kommer sedan att hända med rateAverage ?Jag rekommenderar starkt att du beräknar det baserat på rateCount och rateValue på klientsidan är det enkelt att uppdatera rateAverage med mongoquery , men du borde inte göra det. Varför? Det enkla svaret är:det här är ett mycket enkelt jobb för klienten att hantera den här typen av arbeten och att sätta genomsnitt på varje bloggdokument kräver en onödig uppdatering.

den genomsnittliga frågan skulle beräknas som:

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

Med detta tillvägagångssätt får du maximal prestanda med mongodb och du har koll på varje pris baserat på användare, inlägg och datum.



  1. Redis :Hur ställer man in en nyckel lika med värdet på en annan nyckel?

  2. MongoDB inget utrymme kvar på enheten med docker

  3. Dynamiska frågor i MongoDB och Node.js

  4. Optimera din Linux-miljö för MongoDB