with tutorial the para latest framework español desde cero applications database database-design social-networking bit-manipulation bitmask

database - tutorial - the django project



¿Existe una forma elegante de almacenar una relación dual(es decir, el usuario 1 y el usuario 2 son amigos) (5)

Me he encontrado con el mismo problema en dos trabajos diferentes este mes:

Version 1: User 1 & User 2 are friends Version 2: Axis 1 & Axis 2 when graphed should have the quadrants colored...

El problema es que no veo una manera elegante, usando un RDBMS, para almacenar y consultar esta información.

Hay dos enfoques obvios:

Enfoque 1:

store the information twice (i.e. two db rows rows per relationship): u1, u2, true u2, u1, true u..n, u..i, true u..i, u..n, true have rules to always look for the inverse on updates: on read, no management needed on create, create inverse on delete, delete inverse on update, update inverse Advantage: management logic is always the same. Disadvantage: possibility of race conditions, extra storage (which is admittedly cheap, but feels wrong)

Enfoque 2:

store the information once (i.e. one db row per relationship) u1, u2, true u..n, u..i, true have rules to check for corollaries: on read, if u1, u2 fails, check for u2, u1 on create u1, u2: check for u2, u1, if it doesn''t exist, create u1, u2 on delete, no management needed on update, optionally redo same check as create Advantage: Only store once Disadvantage: Management requires different set of cleanup depending on the operation

Me pregunto si hay un tercer enfoque que sigue las líneas de "clave usando f (x, y) donde f (x, y) es único para cada combinación x, y y donde f (x, y) === f (y, x) "

Mi instinto me dice que debe haber una combinación de operaciones bit a bit que puedan cumplir estos requisitos. Algo así como una columna doble:

key1 = x && y key2 = x + y

Espero que las personas que pasaron más tiempo en el departamento de matemática y menos tiempo en el departamento de sociología hayan visto una prueba de la posibilidad o imposibilidad de esto y puedan proporcionar un rápido "[Usted es un imbécil,] es fácil de probar (im) posible, mira este enlace "(nombre de llamada opcional)

Cualquier otro enfoque elegante también sería muy bienvenido.

Gracias


"x es un amigo de y".

Defina una tabla de pares (x, y) y aplique una forma canónica, por ejemplo, x <y. Esto asegurará que no pueda tener ambos (p, q) y (q, p) en su base de datos, por lo que se asegurará de "almacenar una vez".

Cree una vista como SELECT x, y FROM FRIENDS UNION SELECCIONE x como y, y como x FROM FRIENDS.

Haga sus actualizaciones en la tabla base (inconveniente: los actualizadores deben conocer la forma canónica impuesta), haga sus consultas en contra de la vista.


En SQL es fácil implementar las restricciones para respaldar su primer enfoque:

CREATE TABLE MutualFriendship (u1 VARCHAR(10) NOT NULL, u2 VARCHAR(10) NOT NULL, PRIMARY KEY (u1,u2), FOREIGN KEY (u2,u1) REFERENCES MutualFriendship (u1,u2)); INSERT INTO MutualFriendship VALUES (''Alice'',''Bob''), (''Bob'',''Alice'');


Para cualquiera que esté interesado, jugué con algunas operaciones bit a bit y descubrí que lo siguiente parece cumplir los criterios para f (x, y):

#Python, returns 3 tuple def get_hash(x, y): return (x & y, x | y, x * y)

No puedo probarlo, sin embargo.


Parece que limita el número de amigos a 1. Si este es el caso, entonces usaría algo como u1, u2 u2, u1 u3, null u4, u5 u5, u4

u3 no tiene un amigo


También hay una forma de usar el segundo enfoque agregando una restricción adicional. Compruebe que u1 < u2 :

CREATE TABLE User ( Name VARCHAR(10) NOT NULL , PRIMARY KEY (Name) ) ; CREATE TABLE MutualFriendship ( u1 VARCHAR(10) NOT NULL , u2 VARCHAR(10) NOT NULL , PRIMARY KEY (u1, u2) , FOREIGN KEY (u1) REFERENCES User(Name) , FOREIGN KEY (u2) REFERENCES User(Name) , CHECK (u1 < u2) ) ;

Las reglas para leer, crear, insertar o actualizar tendrán que usar (LEAST(u1,u2), GREATEST(u1,u2)) .