2011-08-24 2 views
3

J'essaie actuellement de trier et trier par une clé avec trois valeurs. Mais Commençons par la structure du document:CouchDB interrogation et filtrage par trois touches indexées

{ 
    _id: "DOCIDGOESHERE01", 
    type: "MESSAGE", 
    date: "2011-08-24 06:49:02", 
    author: "USERIDGOESHERE01", 
    receiver: ["USERIDGOESHERE02", "USERIDGOESHERE03"], 
    message: "ok let's do this" 
} 

L'objectif principal est d'interroger CouchDB pour les messages envoyés par les utilisateurs sélectionnés à un utilisateur spécifique et de les commander à la date. Certains messages n'ont pas de récepteur qui indique qu'ils sont publics et peuvent être lus par n'importe qui.

La fonction carte J'utilise actuellement ressemble à ceci:

function map(doc) { 
    if(doc.receiver.lenth==0) 
     emit([doc.date, null, doc.author], doc._id); 
    else for(var idx in doc.receiver) 
     emit([doc.date, doc.receiver[idx], doc.author], doc._id); 
} 

Lorsque vous interrogez l'interface HTTP CouchDB i tryed demandes comme

HTTP GET xxx/messages?key=[{}, "USERIDGOESHERE02", {}] 

ou

HTTP POST xxx/messages 
{ 
    keys: [ 
     [{}, "USERIDGOESHERE02", "USERIDGOESHERE01"], 
     [{}, "USERIDGOESHERE02", "USERIDGOESHERE03"], 
     [{}, "USERIDGOESHERE02", "USERIDGOESHERE04"], 
    ] 
} 

mais tous n'a pas abouti à la liste des documents que je voulais produire. Avez-vous des suggestions pour cette tâche? Ou est-il impossible de construire de tels résultats filtrés avec couchDB? Merci beaucoup d'avance!

Répondre

6

Les clés sont toujours triées du plus petit au plus grand, dans une longue liste unidimensionnelle. (J'ai essayé de décrire ceci intuitivement dans The Parable of CouchDB mais aucune idée si j'ai réussi!)

À quoi ressemble un tableau trié du plus petit au plus grand? Si vous lisez toutes les clés d'une vue, la valeur de gauche varie le moins. la valeur moyenne varie plus que la gauche; et la valeur de droite varie le plus. En d'autres termes, les clés de tableau disent à CouchDB, "La première priorité est de trier par key[0], si c'est égal, le départage sera key[1], si ceux-ci sont également égaux, la prochaine condition de départage est key[2], etc ..."

par conséquent, vous voulez probablement vos clés pour ressembler à ceci:

[ "receiver_1", null  , a_date  ], 
[ "receiver_1", "sender_A", some_date ], 
[ "receiver_1", "sender_B", another_date ], 
[ "receiver_2", "sender_A", fourth_date ], 
[ "receiver_3", "sender_C", fifth_date ], 

pour trouver tous les messages pour receiver_1 de sender_B et aussi des messages publics, vous avez besoin de deux requêtes, l'une pour les "receiver_1", null appariements, et un autre pour "receiver_1", "sender_B". Vous voulez connaître n'importe quelle date, vous avez donc besoin d'une plage de lignes correspondant à l'expéditeur/au destinataire. Malheureusement, la requête HTTP POST ne prend pas en charge cela.

Vous pouvez simplement effectuer une requête pour chaque expéditeur sélectionné (même en même temps en utilisant des threads ou une programmation asynchrone). Le récepteur et l'expéditeur sont connus, et cet exemple permet une plage allant de la plus petite valeur (null) à la plus grande ({}), qui comprendra toutes les dates.

?startkey=["receiver_1",null,null]&endkey=["receiver_1",null,{}] 
?startkey=["receiver_1","sender_B",null]&endkey=["receiver_1","sender_B",{}] 

Une autre option consiste à simplifier vos clés et supprimer les dates.

[ "receiver_1", null  ], 
[ "receiver_1", "sender_A"], 
[ "receiver_1", "sender_B"], 
[ "receiver_2", "sender_A"], 
[ "receiver_3", "sender_C"], 
[ "receiver_3", "sender_C"], 
[ "receiver_3", "sender_C"], 
[ "receiver_3", "sender_C"], 
[ "receiver_3", "sender_C"], 

Vous pouvez maintenant effectuer une nouvelle requête avec l'API HTTP POST. Les messages renverront et non classés par date. Ce n'est pas si mal, vous pouvez les trier sur le client (ou une fonction _list). Et rappelez-vous, même dans mon premier exemple, les dates ne sont pas parfaitement triées non plus.

+0

Merci pour votre réponse, la première chose que j'ai dû réaliser en étant nouveau à couchDB est qu'il n'y a pas de caractères génériques comme @ user787145 dit. L'autre chose que j'ai apprise est le fait que les vues peuvent être lues d'un index de départ à un index de fin donné sans filtrer certains documents hors de la liste une fois que les vues sont créées. Cela conduit à la conclusion que la vue elle-même doit inclure les caractéristiques de filtrage. De toute façon, il semble que votre troisième approche soit la plus adaptée à mon cas d'utilisation. – sics

5

Je pense que vous voulez;

emit([doc.author, doc.receiver[idx], doc.date], null); 

Vous pouvez ensuite interroger avec

startkey=["USERID1","USERID2"]&endkey=["USERID1","USERID2",{}] 

ce renverra tous les documents envoyés par UserID1 à UserID2 pour date. {} est un objet vide et, selon les règles du classement de CouchDB, triera plus haut que n'importe quel nombre ou chaîne, d'où la garantie ici d'inclure toutes les dates possibles.

Enfin, je noterai que CouchDB ne supporte pas les caractères génériques.

+0

Merci pour votre réponse! Parce que la réponse de @JasonSmith était plus détaillée, j'ai décidé de marquer sa réponse comme la réponse - mais j'ai aimé le vôtre aussi! – sics