2012-10-22 7 views
2

J'ai des documents dans couchdb. Le schéma ressemble ci-dessous:Déduplication/correspondance dans Couchdb?

userId 
email 
personal_blog_url 
telephone 

Je suppose que deux utilisateurs sont en fait la même personne aussi longtemps qu'ils ont

  • email ou
  • personal_blog_url ou
  • téléphone

être identique.

J'ai 3 vues créé, qui associe essentiellement un email/BLOG_URL/téléphone UserIds et combine ensuite les UserIds dans le groupe sous la même clé, par exemple,

_view/by_email: 
---------------------------------- 
key     values  
[email protected] [123, 345] 
[email protected] [23, 45, 333] 

_view/by_blog_url: 
---------------------------------- 
key     values  
http://myblog.com [23, 45] 
http://mysite.com/ss [2, 123, 345] 

_view/by_telephone: 
---------------------------------- 
key     values  
232-932-9088   [2, 123] 
000-111-9999   [45, 1234] 
999-999-0000   [1] 

Mes questions:

  • Comment puis-je fusionner les résultats des 3 vues différentes dans une table/vue utilisateur finale qui ne contient aucun doublon?
  • Ou est-ce une bonne pratique de faire une telle déduplication dans couchdb?
  • Ou ce qui serait un bon moyen de faire une déduplication dans un canapé alors?

ps. dans la vue de face, supposons que pour tous les dupes, nous gardons seulement le plus petit userId.

Merci.

Répondre

2

Bonne question.Peut-être que vous pourriez écouter _changes et rechercher les champs que vous voulez être unique pour l'utilisateur réel dans les vues que vous avez suggéré (by_*).

  • Fusionner les vues dans un (champs émettront différents dans une carte):

    fonction

    (doc) { if (!!! Doc.email || || doc.personal_blog_url doc.telephone) revenir; emit ([1, doc.email], [id.doc]); emit ([2, doc.personal_blog_url], [id.doc]); emit ([3, doc.téléphone], [id.doc]); }

  • fusionner les listes de id dans

  • réduisent
  • Lorsque le nouveau document dans les changements arrive nourrir, vous pouvez interroger la vue avec keys=[[1, email], [2, personal_blog_url], ...] et fusionner les trois listes. Si son ID minimal est inférieur au document modifié, mettez à jour le champ realId, sinon mettez à jour les documents de la liste avec l'ID modifié.

Je suggère d'utiliser un document différent pour stocker { userId, realId } relation.

+0

Merci Marcin. Je pense que votre idée fonctionne. Je n'ai pas eu de succès jusqu'à la dernière étape - la recherche en utilisant plusieurs clés. si je mets 'keys = [[1," [email protected] "], [2," http://a.com "], [3," 334-333-2323 "]]', je reçois toujours tous les documents correspondent en tant que résultat. peut-être que je devrais poser une nouvelle question sur stackoverflow pour cela? – greeness

+0

Je ne suis pas sûr de ce que vous voulez dire par "tous les documents". Sans utiliser reduce (juste map) vous devriez obtenir l'enregistrement JSON de réponse avec '" rows ": [{" id ":" 1 "," key ": [1," some @ email "]," value ":" 1 "}, {" id ":" 2 "," clé ": [1," certains @ email "]," valeur ":" 2 "}, ...}]' pour tous les documents contenant email, URL du blog ou numéro de téléphone comme dans votre nouvel album. Avez-vous obtenu un document qui n'a pas de correspondance de champ? Notez que pour les cartes (sans réduction), les documents ne seront pas triés par identifiant. –

+0

Je suppose '? Keys = [[1," [email protected] "], [2," http://a.com "], [3," 334-333-2323 "]]' est un multiple clé-requête. Le résultat obtenu contient des documents qui n'ont aucun de ces champs correspondants. Si je ne fais qu'une seule requête, le résultat est correct. Y a-t-il un problème avec la requête multi-clé? BTW, j'utilise couchDB 1.0.1. – greeness

1

Vous ne pouvez pas créer de nouveaux documents en utilisant simplement une vue. Vous auriez besoin d'une tâche quelconque pour effectuer la fusion.

Voici une idée.

Au lieu de créer 3 vues, vous pouvez créer un point de vue (qui indexe les données si elle existe):

Key        Values 
---        ------ 
[userId, 'phone']    777-555-1212 
[userId, 'email']    [email protected] 
[userId, 'url']     favorite.url.example.com 

Je ne stocker quoi que ce soit d'autre que la valeur brute, comme vous finiriez avec beaucoup de duplication inutile des données (si vous avez stocké l'objet complet par exemple).

Puis, à interroger, vous pourriez faire quelque chose comme:

...startkey=[userId]&endkey=[userId,{}] 

qui vous donnera toutes les informations en double comme une série de documents pour cet utilisateur Id. Vous auriez toujours besoin de l'analyser pour voir s'il y avait des doublons. Mais, de cette façon, les résultats seraient bien fusionnés en un seul appel CouchDB.

Here's Un bel exemple d'utilisation de tableaux comme clés sur StackOverflow.

Vous auriez probablement encore chargé le document "utilisateur" d'origine s'il avait d'autres données qui ne faisaient pas partie du processus de déduplication.

Une fois découvert, vous pouvez envisager de nettoyer les données à la volée et d'empêcher la création de nouveaux doublons lorsque de nouvelles données sont entrées dans votre application.

+0

Merci. Cette approche semble fonctionner pour la situation lorsque vous avez des informations en double pour chaque utilisateur. Mais ce dont j'ai besoin, c'est de dédoublonner les utilisateurs (w/userId différent mais ayant un email/url/phone commun). – greeness