1

je le schéma mangouste suivant:

var dataSchema = new Schema({ 
    owner: { type: Schema.ObjectId, ref: 'User' }, 
    time : { type: Date, default: Date.now }, 
    eventCount:Number 
}); 

Pour certains DataObjects le EVENTCOUNT est défini et un nombre positif, pour d'autres DataObjects le EVENTCOUNT est indéfini. Je veux concevoir un indice tel que les requêtes de ce genre sont aussi vite que possible:

db.datacollection.find({owner: <some ID>, eventCount: {$exists:true}, time: {<some time range>}) 

Quelle est la meilleure façon de le faire?

Voici la meilleure solution que je pouvais penser, mais je serais intéressé de savoir si quelqu'un a une meilleure solution:

Ajouter une variable booléenne isEventCount au DataSchema. Configurez le middleware mongoose de sorte que isEventCount soit calculé avant de sauvegarder l'objet sur db avec la logique suivante.

if(eventCount > 0) { 
    isEventCount = true; 
} else { 
    isEventCount = false; 
} 

puis la construction d'un indice comme celui-ci

db.datacollection.ensureIndex({user:1, isEventCount: 1, time:1}) 

et ma requête en cours d'exécution comme celui-ci

db.datacollection.find({owner: <some ID>, isEventCount: true, time: {<some time range>}) 

Il y a des inconvénients couple à cette approche. A savoir:

  1. Je sauvegarde des informations redondantes dans la base de données.
  2. Je dois écrire du code middleware supplémentaire pour y parvenir.
  3. Je dois modifier les entrées existantes dans la base de données.

Quelqu'un connaît-il une meilleure solution ou une bibliothèque qui peut vous aider?

Répondre

0

Vous n'avez pas besoin de passer par tout cela pour obtenir des performances décentes sur cette requête. Utilisation de votre requête existante:

db.datacollection.find({owner: <some ID>, eventCount: {$exists:true}, time: {<some time range>} 

cet indice:

db.datacollection.ensureIndex({user:1, eventCount: 1, time:1}) 

dans la plupart des cas devrait vous donner une bonne performance tout à fait. Évidemment, je ne connais pas la taille ou la distribution de votre ensemble de données existant, mais je pense qu'il faudrait quelque chose d'assez inhabituel pour que vous ayez besoin de créer un drapeau isEventCount.

D'une manière générale avant de prendre des mesures inhabituelles avec la conception du schéma dans MongoDB je ferais ce qui suit:

1) Mettre en place des données d'essai avec des volumes raisonnables 2) Essayez vos requêtes à l'aide d'expliquer()

Il vous donnera une bonne idée de la performance de la requête et de la façon dont elle utilise les index.

http://docs.mongodb.org/manual/reference/method/cursor.explain/#cursor.explain

+0

J'ai essayé ceci. Cela ne fonctionne pas.Imaginez que j'ai les données suivantes: {propriétaire: UserA, dataCount: 1, heure: hier} {propriétaire: UserA, dataCount: 1, heure: lastYear} - Imaginez qu'il y a 1000000 enregistrements comme celui-ci {propriétaire: UserA, dataCount: 2, heure: hier} L'index que vous avez décrit ci-dessus classerait les enregistrements de la manière que j'ai décrite ci-dessus. Et puis si je devais exécuter la requête: find ({propriétaire: UserA, eventCount: {$ exists: true}, heure: {depuis hier}}) le curseur devrait analyser tous les enregistrements de l'année dernière. –

+0

"ne fonctionne pas" signifie que la requête échoue? ou vous n'aimez pas la performance? vous pouvez laisser tomber le champ de temps de l'index - comme je l'ai dit je ne connais pas la taille et la distribution de vos données, seulement vous le faites. le point est que vous n'avez pas besoin du champ calculé "isEventCount". Dans tous les cas, vous devriez comparer les différentes approches pour voir ce qui fonctionne pour vous - aucune approche de schéma/indexation ne fonctionnera pour toutes les personnes et tous les cas d'utilisation. –

+0

Ne fonctionne pas comme je n'aime pas la performance. Je veux concevoir mes index d'une manière où pour cette requête particulière, je veux 'nscanned' pour égaler le nombre d'objets trouvés. Avec mon schéma suggéré qui est possible avec votre schéma qui n'est pas possible. (C'est le cas pour l'ensemble de données jouet suivant: '{" datacount ": 1," time ": ISODate (" 2013-06-10T15: 29: 32.603Z ")," exists ": true} {" datacount " : 2, "time": ISODate ("2014-06-10T15: 29: 32.603Z"), "exists": true} {"datacount": 1, "heure": ISODate ("2014-06-10T15: 29: 32.603Z ")," existe ": vrai}') –

Questions connexes