如何在Stack Overflow上实现类似“有趣的标签”功能?

时间:2010-05-26 16:51:42

标签: php jquery mysql tags

用赏金检查我的其他问题: Finding similar number patterns in table

我正在尝试实施有趣的标记功能。作为参考,这是它在SO上的工作方式:

  1. 我将感兴趣的标签添加到“有趣”列表中(如php,mysql,jquery等)。
  2. 然后,如果显示的任何问题在我的列表中有一些标记,则会使背景变为橙色。
  3. 我理解如何使用jQuery来做到这一点(有相关的问题),但无法弄清楚如何使用MySQL实现后端部分!

    所以这是我的问题:它是如何完成的?我想它的工作方式如下:

    • 每个成员在mysql中都有一行,我们称之为“interested_tags”。
    • 在我通过输入编写并提交我的标签后,它正在连续写入“interested_tags”。
    • 然后,主页面有一个显示所有答案的查询,它总是使用strpos检查问题的标签,如下所示:

      if(strpos($question_tags, $my_tags) === true) {
         //and here will be made background orange
      }
      

    我是否正确或有任何办法吗?

    编辑:那么,你能告诉我一个例子,或者给我一些如何用多对多关系实现这个的技巧吗?感谢。

6 个答案:

答案 0 :(得分:37)

正如其他答案中所提到的,用户和标签之间很可能存在多对多关系,表示为自己的表格。我做了一个简化案例的SQL演示。 InterestingTags表是连接用户对哪些标签感兴趣的表。

/* Create tables */
CREATE TABLE User (id INT NOT NULL AUTO_INCREMENT, name varchar(50), PRIMARY KEY(id));
CREATE TABLE Tag (id INT NOT NULL AUTO_INCREMENT, name varchar(50), PRIMARY KEY(id));
CREATE TABLE InterestingTags (user_id INT NOT NULL REFERENCES User(id), tag_id INT NOT NULL REFERENCES Tag(id), PRIMARY KEY(user_id,tag_id));

/* Insert some data */
/* 3 users, 5 tags and some connections between users and tags */
INSERT INTO User (name) VALUES ('jQueryFreak'), ('noFavoriteMan'), ('generalist'); 
INSERT INTO Tag (name) VALUES ('jQuery'), ('php'), ('asp.net'), ('c#'), ('ruby');
INSERT INTO InterestingTags (user_id, tag_id) VALUES (1,1), (3,1), (3,2), (3,3), (3,4);

/* Select all the users and what tags they are interested in */
SELECT u.name, t.name FROM User u 
LEFT JOIN InterestingTags it ON it.user_id = u.id 
LEFT JOIN Tag t ON t.id = it.tag_id;

/* Select all tag ids that are interesting to user 3 ("generalist") */
SELECT tag_id FROM InterestingTags WHERE user_id = 3;

/* 
    Now let's introduce a questions table.
    For simplicity, let's say a question can only have one tag. 
    There's really a many-to-many relationship here, too, as with user and tag
*/
CREATE TABLE Question (id INT NOT NULL AUTO_INCREMENT, title VARCHAR(50) NOT NULL, tag_id INT NOT NULL REFERENCES Tag(id), PRIMARY KEY(id));

/* Insert some questions */
INSERT INTO Question (title, tag_id) VALUES 
    ('generating random numbers in php', 2),     /*php question*/
    ('hiding divs in jQuery', 1),                /*jQuery question*/
    ('how do i add numbers with jQuery', 1),     /*jQuery question 2*/
    ('asp.net help', 3),                         /*asp.net question */
    ('c# question', 4),                          /*c# question */
    ('ruby question', 5);                        /*ruby question */

/* select all questions and what users are interested in them */
SELECT q.title, u.name FROM Question q
LEFT JOIN InterestingTags it ON it.tag_id = q.tag_id 
LEFT JOIN User u ON u.id = it.user_id;


/* select all questions a user will be interested in. Here the user is jQueryFreak with id = 1 */
SELECT q.id, q.title FROM Question q
LEFT JOIN InterestingTags it ON it.tag_id = q.tag_id
LEFT JOIN User u ON u.id = it.user_id
WHERE u.id = 1;


/* Select all questions and indicate whether or not jQueryFreak (with id = 1) is interested in each one */
/* TODO: make SO question about how to do this as efficient as possible :) */
SELECT q.id, q.title,
    (SELECT COUNT(*) FROM InterestingTags it 
    WHERE it.tag_id = q.tag_id AND it.user_id = 1)
    AS is_interested 
FROM Question q;


/* Let's add a many-to-many relationship between questions and tags. 
   Questions can now have many tags 
*/
ALTER TABLE Question DROP COLUMN tag_id;

CREATE TABLE Question_Tag ( 
    question_id INT NOT NULL REFERENCES Question (id),
    tag_id      INT NOT NULL REFERENCES Tag (id),
    PRIMARY KEY (question_id, tag_id)
);

/* Insert relationships between questions and tags */
INSERT INTO Question_Tag VALUES
    /* First the tags as in the above examples */
    (1,2), (2,1), (3,1),(4,3),(5,4),(6,5),
    /* And some more. ASP.NET question is also tagged C#
    and php question is tagged jQuery */
    (1,1), (4,4);


/* select all questions and what users are interested in them
(Some combinations will show up multiple times. This duplication is removed in the 
two following queries but I didn't find a solution for it here)*/
SELECT q.title, u.name FROM Question q
LEFT JOIN Question_Tag qt ON qt.question_id = q.id /* <-- new join */
LEFT JOIN InterestingTags it ON it.tag_id = qt.tag_id 
LEFT JOIN User u ON u.id = it.user_id;


/* select all questions a user will be interested in. Here the user is jQueryFreak with id = 1 */
SELECT q.id, q.title FROM Question q
LEFT JOIN Question_Tag qt ON qt.question_id = q.id /* <-- new join */
LEFT JOIN InterestingTags it ON it.tag_id = qt.tag_id
LEFT JOIN User u ON u.id = it.user_id
WHERE u.id = 1
GROUP BY q.id; /* prevent duplication of a question in the result list */


/* Select all questions and indicate whether or not jQueryFreak (with id = 1) is interested in each one */
/* STILL TODO: make SO question about how to do this as efficient as possible :) */
SELECT q.id, q.title,
    (SELECT COUNT(*) FROM InterestingTags it
     WHERE it.tag_id = qt.tag_id AND it.user_id = 1)
    AS is_interested 
FROM Question q
LEFT JOIN Question_Tag qt ON qt.question_id = q.id /* <-- new join */
GROUP BY q.id;


更新:添加了php演示
请记住在运行演示之前更改mysql常量

这样做是向DB运行两个查询:

  • 一个问所有问题及其标签
  • 询问用户感兴趣的标签。

要使用其代码“标记”问题,它会为其所属的每个代码添加class - 例如标记为jQuery的问题(其中jQuery的标识为1)和php(标识为2)将包含类tagged-1和{{1} }。

现在将此与其他查询相结合,获取有趣的标签,您只需选择具有与感兴趣的标签相对应的类的问题并对其进行样式化。例如,如果您对ID为tagged-21的代码感兴趣,那么它将是以下jQuery代码3

$('.tagged-1, .tagged-3').addClass('interesting-tag');

答案 1 :(得分:7)

  

每个mysql都有一行   会员,我们来称呼它   “interested_tags”。

更有可能的是,还有一个表格代表用户和标签之间的多对多关系。使用另一个表格将标签与问题相关联。

然后你只需要一个查询(或者更可能是存储过程),将用户的标签与问题的标签进行比较,并返回布尔值true或false。

答案 2 :(得分:3)

Stack Overflow标记在标记中至少使用*,因此将标记存储在数组中并使用模式匹配进行迭代(无论您是使用glob,SQL还是正则表达式,都无关紧要)只要用户知道将使用哪个。)

答案 3 :(得分:2)

@new question:http://skmzq.qiniucdn.com/data/20060423142114/index.html包含不同类型标记的(旧的但有用的)比较。不要忘记阅读评论,它们非常有用。

答案 4 :(得分:2)

这可能会启发你。 正如凯利所说,在页面加载后,它是在Javascript中完成的。据我所知,他们加载了所有问题的所有标签,以及与右侧标签相同的标签,它们会突出显示。请参阅alt text

答案 5 :(得分:1)

从页面渲染的方式来看,我猜测标签比较是在JavaScript中完成的。所以步骤将是:

  • 查询用户感兴趣的标签
  • 将结果提供给客户端JS
  • JS迭代每个问题并根据匹配更改属性(如果匹配“忽略”标记,则包括删除帖子。