Mirki mam taki problem do rozwiązania w SQL. W serwisie jest N użytkowników i każdy z nich może odnzaczyć innego użytkownika jako zaufanego. Drugi użytkownik może zrobić również to samo. I chciałbym żeby w kontekście np. użytkownika nr 1 mógł wybrać wszystkie osoby którym on zaufał ale które również odwzajemniły jego zaufanie.
I teraz zastanawiam się jak to zrobić...
myślałem żeby zrobić osobną tabelkę userfriends { userId, friendId , isTrusted } i po prostu w momencie jak użytkownik #1 dodaje do zaufanych użytkownika #2 to dopisywać do userfriends { 1 , 2 , false }. Potem gdy drugi użytkownik dodaje do zaufanego użytkownika nr 1 to dopisywać user_friends { 2 , 1 , false }; i przy akcji dodawania do zaufanych zrobić selecta i jeśli po operacj "dodaj do zaufanych" istnieje sytuacja w której dodajemy do zaufanych osobe która już nas dodała to w obu wierszach oznaczyć isTrusted na true. Potem przy wyszukiwaniu osób ze wzajemnym zaufaniem mogę tylko zrobić select * from userfriends where userId = ? and isTrusted = true....
ale boje się że w produkcyjnej wersji z replikacją bazy danych i skalowaniem poziomym serwisu na N instancji to się zesra bo request w którym #2 dodaje do zaufanych #1 może "wystrzelić" w momencie kiedy operacja dodawania #1 do #2 się nie zakończy i ostatecznie wyjdzie tak że w userfriends będą dwa wpisy bez oznaczenia isTrusted, tj. { 1,2,false } oraz { 2,1,false }.
myślałem też żeby rozbić to na poszczególne operacje tzn. bez pola isTrusted i tylko ddoawać do userfriends ( 1,2 ) w przpyadku gdy #1 zaufa #2 a potem dodać do userfriends (2,1) gdy #2 zaufa #1. Ale wtedy pojawia się problem wyodrębnienia "pokaż mi wszystkich użytkowników którym ja zaufałem a oni odzwajemnili zaufanie", bo nie wiem musiałbym jakoś tabelę user_friends zjoinować samą ze sobą?? bo pytając o to w kontekscie użytkownika #1 musiałbym zrobić coś w stylu (pseudo-sqlem)
SELECT * FROM userfriends WHERE userId = 1 LEFT JOIN userfriends ON friendId = userId LIMIT 1
problem w tym że nie wiem jaka jest wydajność takiego zapytania i czy wogóle jest możliwość zjoinowania tabeli samej ze sobą. ta funkcja będzie dość często używana w systemie więc musi być skalowalna odpowiednio.
myślałem też nad bardziej łopatologicznym rozwiązaniem, przy sktrukturze takiej jak powyżej user_friends { userId , friendId } po prostu zrobić (w kontekscie użytkownika #1):
friends = DB.query('SELECT * FROM user_friends WHERE userId = 1')
i potem ze wszystkich wpisów zwróconych przez bazę pobrać tylko takie które odzwajemniły relacje: trustedFriends = DB.query( 'SELECT * FROM user_friends WHERE userId IN [...friends] AND friendId = 1' ).
Który sposób najlepszy? A może spróbować jakiegoś innego jeszcze?
1. użytkownik może dodać innego do zaufanych 2. drugi użytkownik może dodać pierwszego do zaufanych 3. musze mieć możliwość wyciągać z bazy użytkowników którzy wzajemnie sobie
@larvaexotech: 3 sposób ok, ale zamiast IN użyj EXISTS: SELECT cośtam FROM userFriends uf WHERE EXISTS (SELECT * FROM userFriends WHERE uf.userId = friendId AND uf.friendId = userId)
Mirki mam taki problem do rozwiązania w SQL. W serwisie jest N użytkowników i każdy z nich może odnzaczyć innego użytkownika jako zaufanego. Drugi użytkownik może zrobić również to samo. I chciałbym żeby w kontekście np. użytkownika nr 1 mógł wybrać wszystkie osoby którym on zaufał ale które również odwzajemniły jego zaufanie.
I teraz zastanawiam się jak to zrobić...
myślałem żeby zrobić osobną tabelkę userfriends { userId, friendId , isTrusted } i po prostu w momencie jak użytkownik #1 dodaje do zaufanych użytkownika #2 to dopisywać do userfriends { 1 , 2 , false }. Potem gdy drugi użytkownik dodaje do zaufanego użytkownika nr 1 to dopisywać user_friends { 2 , 1 , false }; i przy akcji dodawania do zaufanych zrobić selecta i jeśli po operacj "dodaj do zaufanych" istnieje sytuacja w której dodajemy do zaufanych osobe która już nas dodała to w obu wierszach oznaczyć isTrusted na true. Potem przy wyszukiwaniu osób ze wzajemnym zaufaniem mogę tylko zrobić select * from userfriends where userId = ? and isTrusted = true....
ale boje się że w produkcyjnej wersji z replikacją bazy danych i skalowaniem poziomym serwisu na N instancji to się zesra bo request w którym #2 dodaje do zaufanych #1 może "wystrzelić" w momencie kiedy operacja dodawania #1 do #2 się nie zakończy i ostatecznie wyjdzie tak że w userfriends będą dwa wpisy bez oznaczenia isTrusted, tj. { 1,2,false } oraz { 2,1,false }.
myślałem też żeby rozbić to na poszczególne operacje tzn. bez pola isTrusted i tylko ddoawać do userfriends ( 1,2 ) w przpyadku gdy #1 zaufa #2 a potem dodać do userfriends (2,1) gdy #2 zaufa #1. Ale wtedy pojawia się problem wyodrębnienia "pokaż mi wszystkich użytkowników którym ja zaufałem a oni odzwajemnili zaufanie", bo nie wiem musiałbym jakoś tabelę user_friends zjoinować samą ze sobą?? bo pytając o to w kontekscie użytkownika #1 musiałbym zrobić coś w stylu (pseudo-sqlem)
SELECT * FROM userfriends WHERE userId = 1 LEFT JOIN userfriends ON friendId = userId LIMIT 1
problem w tym że nie wiem jaka jest wydajność takiego zapytania i czy wogóle jest możliwość zjoinowania tabeli samej ze sobą. ta funkcja będzie dość często używana w systemie więc musi być skalowalna odpowiednio.
myślałem też nad bardziej łopatologicznym rozwiązaniem, przy sktrukturze takiej jak powyżej user_friends { userId , friendId } po prostu zrobić (w kontekscie użytkownika #1):
friends = DB.query('SELECT * FROM user_friends WHERE userId = 1')
i potem ze wszystkich wpisów zwróconych przez bazę pobrać tylko takie które odzwajemniły relacje:
trustedFriends = DB.query( 'SELECT * FROM user_friends WHERE userId IN [...friends] AND friendId = 1' ).
Który sposób najlepszy? A może spróbować jakiegoś innego jeszcze?
1. użytkownik może dodać innego do zaufanych
2. drugi użytkownik może dodać pierwszego do zaufanych
3. musze mieć możliwość wyciągać z bazy użytkowników którzy wzajemnie sobie
SELECT
cośtam
FROM userFriends uf
WHERE EXISTS (SELECT * FROM userFriends WHERE uf.userId = friendId AND uf.friendId = userId)