【问题标题】:How can I efficiently store a 2-way "like" system similar to Tinder?如何有效地存储类似于 Tinder 的 2 路“喜欢”系统?
【发布时间】:2015-04-10 02:28:52
【问题描述】:

在 Tinder 上,当 2 个成员互相喜欢时,他们就是“匹配”并且能够交流。如果只有一个成员喜欢另一个成员,那就不匹配了。

我正在尝试将这个“Like”系统存储在 MySQL 中,但无法找到高效的最佳方法。这是我现在的设置。

mysql> desc likes_likes;
+--------------+----------+------+-----+---------+----------------+
| Field        | Type     | Null | Key | Default | Extra          |
+--------------+----------+------+-----+---------+----------------+
| id           | int(11)  | NO   | PRI | NULL    | auto_increment |
| from_user_id | int(11)  | NO   | MUL | NULL    |                |
| to_user_id   | int(11)  | NO   | MUL | NULL    |                |
| value        | int(11)  | NO   |     | NULL    |                |
| created_at   | datetime | NO   |     | NULL    |                |
| updated_at   | datetime | YES  |     | NULL    |                |
+--------------+----------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

要找到我的匹配项,我会查询类似...

SELECT to_user_id FROM likes_likes WHERE from_user_id = my_id AND value = 1 AND .... I don't know how to join the same table from here.

如何在这个表上执行查询?如果效率不高,有什么更好的结构来存储这个模型?

1 喜欢,0 不喜欢。这些是仅有的 2 个值。

【问题讨论】:

  • 什么是value1 喜欢,-1 讨厌? 0 不喜欢,10 喜欢?...

标签: mysql sql database indexing


【解决方案1】:
SELECT A.from_user_id AS userA, B.from_user_id AS userB
FROM likes_likes A
JOIN likes_likes B
  ON A.from_user_id = B.to_user_id
  AND A.to_user_id = B.from_user_id
  AND A.id <> B.id
WHERE A.value = 1
  AND B.value = 1

【讨论】:

  • 谢谢。我需要索引什么才能有效扩展? user_ids 已经是外键,而且我在 (from_user_id, to_user_id) 上已经有一个唯一的
  • 实际上,(from_user_id, to_user_id) 可能也是我会选择的。
  • &lt;&gt; 是什么意思?
  • 如何为某个用户检查这个?例如,我想获取“from_user_id”为 5 的所有匹配项。
  • 其中&gt;= 是“大于或等于”,&lt;= 是“小于或等于”,同样的比喻&lt;&gt; 是“大于或小于”,即“不等于”。在 MySQL 中,它是 != 的同义词,最近已成为标准;较旧的编程语言往往有&lt;&gt;。检查某个用户:... WHERE ... AND A.from_user_id = 5.
【解决方案2】:

要查找匹配项,您可以使用带别名的常规连接:

SELECT l1.from_user_id user1, l2.from_user_id user2
FROM likes_likes l1
INNER JOIN likes_likes l2 ON
  l2.from_user_id = l1.to_user_id AND
  l1.to_user_id = l2.from_user_id AND
  l1.value = 1 AND l2.value = 1

第一个条件检查user1 是否喜欢user2 以及user2 是否喜欢至少另一个人。

第二个条件完成了检查,所以我们现在有两个人互相表达了意见。

最后两个检查确保他们都喜欢彼此:)

【讨论】:

  • 谢谢杰克。如何为某个用户检查这个?例如,我想获取“from_user_id”为 5 的所有匹配项。
  • @TIMEX 放在 WHERE 子句中
【解决方案3】:

这是一种使用group by least(),greatest() 将每个唯一的用户对放入一个组,然后检查每个组是否有 2 行的方法

select least(from_user_id,to_user_id), greatest(from_user_id,to_user_id)
from likes_likes
where value = 1
-- and my_id in (from_user_id,to_user_id)
group by least(from_user_id,to_user_id), greatest(from_user_id,to_user_id)
having count(*) = 2

如果同一用户可以多次点赞另一个用户(即用户“A”两次点赞用户“B”),则使用having count(distinct from_user_id) = 2

【讨论】:

    【解决方案4】:

    你真的需要value吗?如果没有行,就没有喜欢。从这个查询中你应该得到1 匹配和0 没有相互匹配。

    SELECT 
      COUNT(*) 
    FROM 
      likes_like i_like_you
     JOIN likes_like you_like_me ON i_like_you.to_user_id = you_like_me.from_user_id
    WHERE 
      i_like_you.from_user_id = @my_id
      AND you_like_me.from_user_id = @your_id
    

    【讨论】:

    • 我觉得你也需要and value = 1
    • @Bohemian 如果您只为点赞添加一行,则可以忽略价值。使用它意味着您还将存储所有不喜欢的内容,这意味着更多的行。没有喜欢的行不能暗示不喜欢。
    • 您需要跟踪不喜欢的人,否则他们会不断弹出 :)
    【解决方案5】:

    id有什么理由吗?看起来这对(from_user_idto_user_id)应该是唯一的,因此可能是“自然的”PRIMARY KEY

    我还没有看到任何需要 value 的好论据。

    所以桌子缩小到了

    CREATE TABLE likes_likes (
        from_user_id ...,
        to_user_id ...,
        created_at ...,
        updated_at ...,
        PRIMARY KEY(from_user_id, to_user_id), -- serves as the necessary INDEX.
    ) ENGINE=InnoDB;
    
    SELECT  A.from_user_id AS userA,
            B.from_user_id AS userB
        FROM  likes_likes A
        JOIN  likes_likes B
             ON  A.from_user_id = B.to_user_id
            AND  A.to_user_id = B.from_user_id
    

    (我假设您不允许喜欢自己的人。)

    【讨论】:

    • “我还没有看到任何需要value 的好论据”:正如@DaveAnderson 在他的回答下面所说,有三种情况:未评判(缺席),评判有利(@987654328 @ 是 1) 并被判定为不利(value0)。没有value,您只有两种可能:行缺失或存在。这使得无法区分用户是否已经看到并取消了配对,或者它是从未向用户展示过的新配对。
    猜你喜欢
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 2018-05-27
    • 2022-12-13
    • 1970-01-01
    • 1970-01-01
    • 2013-05-26
    相关资源
    最近更新 更多