我如何找到相关的讲座?

时间:2015-12-17 15:51:13

标签: c# algorithm

我有一个网站,显示有关可用讲座的信息。每个讲座都有一个标题,一个相关的演讲者,以及(可能)多个类别。数据库模式看起来像这样(警告:这是空中代码,因为我没有在我面前有数据库)...

create table Lectures (
  ID int not null identity(1,1) primary key,
  Title varchar(max) not null default '',
  SpeakerID int not null foreign key references Speakers(ID)
)

create table Categories (
  ID int not null identity(1,1) primary key,
  Name varchar(max) not null default ''
)

create table Lectures_Categories (
  ID int not null identity(1,1) primary key,
  LectureID int not null foreign key references Lectures(ID),
  CategoryID int not null foreign key references Categories(ID)
)

在查看有关讲座的详细信息时,我希望能够推荐相关讲座,但我不确定如何编写这个。我最初的想法是,以下标准将用于计算相关性(最重要的是第一个)...

  • 常见类别 - 即两个讲座共享的类别越多,相关的可能性越大
  • 标题中的相似性 - 即两个讲座共享的单词越多,它们相关的可能性就越大。
  • 同一位发言人

如果根据上述标准对两个讲座进行同等排名,我希望将较新的讲座排在旧标准之上。

任何人都知道如何编写这个?我在C#中执行此操作,如果任何相关的SQL Server数据库使用实体框架模型。

1 个答案:

答案 0 :(得分:1)

让我理解基本思路:假设所有三个条件都可以在sql查询中表达,那么你应该得到加权结果集,然后你union一起。

第一个只是select ID, 10 as weight from lectures where ID <> ourLectureID and speakerID = ourSpeakerID

第二个是join超过LecturesTopics,权重较小,可能是4

现在让我们忽略第三个查询的问题。

现在我们已经设置了result1个ID和权重,我们就组了一个组&amp;和。我的sql今天相当生疏,但我想的是这样的事情:select max(ID), sum(weight) as ranking from result1 group by ID order by ranking ..完成!

现在我已经差不多20年没碰过SQL服务器了;-)但是我觉得它不适合创建第三个查询。数据库设计师只会给你一个有趣的外观,并告诉你查询标题是糟糕的坏事;并且'为什么你没有添加keywords表.. ??

如果您不想这样做,我认为您可以将所有标题提取到C#应用程序中并使用其字符串/集合/ LINQ功能过滤掉有趣的单词并使用第三个排名创建第三个查询;也许只有4个字母以上的大写字母..?

<强>更新

以下是如何在一系列行中找到最佳拟合线的一个很小的例子:

List<string> proverbs = new List<string>();
List<string> cleanverbs = new List<string>();
List<string> noverbs = new List<string>();

private void button1_Click(object sender, EventArgs e)
{
    noverbs.AddRange(new[] { "A", "a", "by", "of", "all", "the", "The", 
        "it's", "it", "in", "on", "is", "not", "will", "has", "can", "under" });

    proverbs = File.ReadLines("D:\\proverbs\\proverbs.txt").ToList();
    cleanverbs = proverbs.Select(x => cleanedLine(x)).ToList();
    listBox1.Items.AddRange(proverbs.ToArray());
    listBox2.Items.AddRange(cleanverbs.ToArray());
}

string cleanedLine(string line)
{
    var words = line.Split(' ');
    return String.Join(" ", words.ToList().Except(noverbs) );
}

int countHits(string line, List<string> keys)
{
    var words = line.Split(' ').ToList();
    return keys.Count(x => words.Contains(x));
}

private void listBox2_SelectedIndexChanged(object sender, EventArgs e)
{
    string line = listBox2.SelectedItem.ToString();
    int max = 0;
    foreach (string proverb in cleanverbs)
    {
        var keys = proverb.Split(' ').ToList();
        int count = countHits(line, keys);
        if (count > max && proverb != line)
        {
            max = count;
            Text = proverb + " has " + max + " hits";
        }
    }
}

它使用了两个列表框和一个谚语的文本文件。加载后,您可以单击第二个列表框,窗口标题将显示点击次数最多的行。

您需要进行一些更改:

  • 从您的数据库中提取您的标题,包括其键
  • 使用非动词创建更广泛且可扩展的文件
  • 决定混合案例
  • 创建不是一个结果而是一组有序的行
  • 可能会优化一些内容,因此您不必多次拆分标题正文