J'ai une database potentielle de 5 millions d'users, où chaque user a un certain nombre d'amis. Ce que je dois faire est de mettre en œuvre la search, de sorte que les users peuvent filterr selon certains attributes (c'est-à-dire le sexe d'un autre user, etc.), cette partie est assez simple.
L'user A search tous les mâles et obtient le jeu de résultats. Utilisateur B, Utilisateur C, Utilisateur D
Cependant, l'user doit également avoir la possibilité de sortinger les résultats de la search par le nombre d'amis communs que l'user A a avec tous les users du jeu de résultats.
En supposant
Utilisateur A ET Utilisateur B = 3 amis communs
Utilisateur A ET Utilisateur C = 8 amis communs
Utilisateur A ET Utilisateur D = 5 amis communs
- Utilisation des assemblys .net dans SQL Server 2005
- Est-il nécessaire de sérialiser les propriétés lors de l'utilisation de l'état de session sqlserver pour .net 3.5 framework et IIS 7.0
- Existe-t-il une bibliothèque avec une implémentation InsertAllOnSubmit alternative qui utilise SqlBulkCopy?
- Chiffrement SQL Server utilisant un certificate SSL auto-signé. Interrogation à partir d'ASP.NET 3.5
- Comment répéter les valeurs de ligne
Ensuite, la search devrait sortinger les résultats dans l'ordre suivant
Utilisateur C, Utilisateur D, Utilisateur A
En plus de cela, puisque les résultats seront affichés sur une page Web, j'ai également besoin de support pour la pagination, de sorte que toutes les 5 millions d'inputs ne sont pas traitées chaque fois que l'user navigue entre les résultats de search.
Le code web est en train d'être écrit en C #, mais en termes de database, je suis assez ouvert et je peux utiliser SQL, NoSQL ou Redis. La priorité principale est la haute performance, donc Redis semble être une bonne option. Comment mettre en œuvre une telle exigence de search à partir du datastore et du pseudo-code?
En redis, vous voudrez probablement stocker cela dans un zset
; il n'y a pas d'indexing automatique embeddede en rouge, vous aurez donc besoin de zadd
ou zincrby
lorsque vous ajoutez ou supprimez des amis ( zincrby
avec un nombre négatif à soustraire). Ensuite, vous pourriez zrange
ou zrangebyscore
pour l'interroger. Ces methods sont toutes disponibles sous le préfixe StackExchange.Redis
dans le package StackExchange.Redis sur NuGet.
Mes deux centimes.
Vous pourriez profiter de ZINTERSTORE si vous maintenez l'index de genre en tant que Set, et les amis communs countnt comme SortedSet pour chaque user (le score est le nombre d'amis communs). De plus, vous aurez besoin d'un set d'amis par user.
Pour le genre, utilisez un Set avec le format de key: gender:{gender}
et chaque élément sera un identifiant d'user.
Pour les amis, utilisez un Set au format key: friends:{userId}
et chaque élément sera un identifiant user.
Pour les amis communs, utilisez un SortedSet avec le format de key: mutual:{userId}
, chaque élément sera un identifiant d'user et le score sera le nombre d'amis communs.
Ainsi, lorsque vous ajoutez un user, vous faites:
void AddUser(ssortingng user, ssortingng gender) { // Add to a gender set "gender:{gender}"->{users} db.SetAdd($"gender:{gender}", user); }
Pour append une amitié entre deux users:
void AddFriendship(ssortingng user1, ssortingng user2) { // All friends of user1, should increment its mutual count with user2 var user1Friends = db.SetMembers($"friends:{user1}"); foreach(var user1Friend in user1Friends) { db.SortedSetIncrement($"mutual:{user1Friend}", user2, 1); db.SortedSetIncrement($"mutual:{user2}", user1Friend, 1); } // All friends of user2, should increment its mutual count with user1 var user2Friends = db.SetMembers($"friends:{user2}"); foreach (var user2Friend in user2Friends) { db.SortedSetIncrement($"mutual:{user2Friend}", user1, 1); db.SortedSetIncrement($"mutual:{user1}", user2Friend, 1); } // Add to friend sets "friends:{user}->{users}" db.SetAdd($"friends:{user1}", user2); db.SetAdd($"friends:{user2}", user1); }
Et pour get les users par sexe classés par nombre d'amis communs:
static IEnumerable<ssortingng> GetUsersByGenderOrderByMutualFriends(ssortingng user, ssortingng gender) { var db = mux.GetDatabase(); var tempKey = "temp"; db.SortedSetCombineAndStore(SetOperation.Intersect, tempKey, $"gender:{gender}", $"mutual:{user}", Aggregate.Sum); var result = db.SortedSetRangeByRank(tempKey, 0, -1, Order.Descending).Select(x => x.ToSsortingng()); db.KeyDelete(tempKey); return result; }