0

I am trying to store signalR groups in Dictionary>

But i do not know how to lookup a string value in HashSet and return key string?

    var dict = new Dictionary<string, HashSet<string>>();
    dict["GroupA"] = ["user1","user2","user3"];
    dict["GroupB"] = ["user3", "user4"];
    dict["GroupC"] = ["user4","user5","user6"];

I want to lookup for "user3" and it should returns ["GroupA","GroupB"]. I do not know about that how to use dictionaries in c#. I have around ~20k groups and many of users in it. Does it handle too much groups and users with singleton pattern (store in memory)?

Hope someone help me with an working example. I am beginner here. Thanks!

Neil
  • 11,059
  • 3
  • 31
  • 56
user3565914
  • 51
  • 1
  • 9
  • "I want to lookup for "user3" and it should returns ["GroupA","GroupB"]." If you want to look up members by group, you should be storing members by group, groups by member!. – AKX Feb 05 '20 at 17:10
  • I'm trying to do achieve this: there are too many groups about ~20k and users will subscribe a list of them. An user logged in and send a list of groups ids. Hub will add this user to groups. It's okay. But if this user send a new group list, then hub should remove this user from all joined groups and add this user to this new group ids list to subscribe. Do you have an idea to solve this problem? Thanks @AKX – user3565914 Feb 05 '20 at 17:56
  • For a simple solution (that may be somewhat memory intensive for 20k groups), store both "username-to-groupnames" and "groupname-to-usernames" dictionaries. – AKX Feb 05 '20 at 18:10
  • It makes too many multiples, doesn't it? Does store them in sql and fetch from there again is good idea or not? Because, for 5k users 20.000x5.000 = 100m so it's really huge data for memory, isn't it? 20k may go over 50k too – user3565914 Feb 05 '20 at 19:11
  • You didn't mention SQL was an option here. If it is, then by all means do that - SQL databases excel at this sort of thing. `SELECT group_name FROM user_groups WHERE user_name='foo'`. – AKX Feb 05 '20 at 19:23
  • I'll go with Dictionary> for testing purposes and sql or something similar for realtime. I'll check also redis or memcache in research and develop. Thanks man you helped alot to me!! – user3565914 Feb 05 '20 at 19:26

2 Answers2

0

You need to iterate over the dictionary, and get all the keys that point to a hashset that contains the value you're looking for:

var matches = dict.Where(kvp => kvp.Value.Contains("user3"));

Explanation:
You're asking for all the key-value pairs, where the Value (which we know is of type Hashset) contain the string you're looking for.

Update: to get just the keys from the key-value pairs, I believe you can do this:

var matches = dict.Where(kvp => kvp.Value.Contains("user3")).Select(kvp => kvp.Key);

Further musing: if your use cases will always prioritize finding by user, perhaps you should invert the dictionary: have the user name be the key, and the value would be the groups the user belongs to. That way, finding all groups for a user will be O(1).

Traveling Tech Guy
  • 27,194
  • 23
  • 111
  • 159
  • Besides this being O(n) for all of the "~20k" groups OP has, don't we need to also map the KVPs to something else? – AKX Feb 05 '20 at 17:12
  • if someone have better solutions to map groups and users in a mapper or list. I would be happy to hear it here. – user3565914 Feb 05 '20 at 17:39
0

Answer will depend on the situation:

  • If SQL is an option, then do this in SQL before loading. It is way more efficient in general.
  • If you always need to search by user, flip the dictionary, listing groups by member.
  • If the lookup happens server-side, I would go with two dictionaries: 1 member by group, 1 group by member. That doubles memory usage, but if you can make these singletons serving all clients from same instances that should be a limited impact.
  • If the lookup happens client-side than only load a mini list of groups for each user that they are a member of (either from SQL or from server-side singleton) No need to search any groups for other members in that case I would imagine.
Stefan de Kok
  • 2,018
  • 2
  • 15
  • 19