LINQ:选择具有多个标签的帖子

时间:2015-06-19 19:21:26

标签: c# linq

我正在尝试查找所有帖子包含所有选定的标签。

我当前的代码返回包含所有选定标签的帖子以及包含一些所选标签的帖子。

这是我的功能。感谢您的帮助。

示例数据库结构

[发布]  - ID   - 标题   - 身体

[PostTag]  - ID   - PostId   - TagName

所以[Post]的帖子与PostId的一对多关系是外键。

public static IEnumerable<Post> getPostContainsAllTags(IEnumerable<string> _SelectedTags, 
                                                           int numPosts)
{
    using (MaplePrimesDataContext dc = new MaplePrimesDataContext(_connectionString))
    {

        var tagPosts = (from p in dc.Posts
                        join t in dc.PostTags on p.Id equals t.PostId
                        where p.Status == 1 && _SelectedTags.Contains(t.Name)
                        orderby p.DateAdded descending
                        select p).Take(numPosts).ToList();
        return tagPosts;
    }
}

3 个答案:

答案 0 :(得分:2)

我还会将数据库结构更改为不复制PostTag

中的标记名称

这很有效,很容易理解:

var tagPosts = dc.Posts.Where(post => post.Status == 1);

foreach (var selectedTag in _SelectedTags)
{
    tagPosts = tagPosts.Where(post => post.PostTags.Any(tag => tag.Name == selectedTag));
}

return tagPosts.OrderByDescending(p => p.DateAdded).Take(numPosts).ToList();

这也有效,而且速度更快

var selectedTagIds = dc.Tags.Where(tag => _SelectedTags.Contains(tag.Name)).Select(x => x.TagId);

var tagPosts = dc.Posts
    .Where(post => post.Status == 1)
    .Where(post => 
      !(from selectedTag in selectedTagIds
        join tag in post.PostTags on selectedTag equals tag.TagId into postTags
        from tag in postTags.DefaultIfEmpty()
        where tag.TagId == null
        select 1).Any());

return tagPosts.OrderByDescending(p => p.DateAdded).Take(numPosts).ToList();

这里的区别在于我们首先创建一个数据库集合selectedTagIds,然后使用它来进行左连接(在LINQ中非常难看 - &gt; https://msdn.microsoft.com/en-us/library/bb397895.aspx

它有效,因为如果帖子没有标记,那么该帖子标记和所选标记的左连接将有一行没有帖子标记。

答案 1 :(得分:0)

dc.Posts.Select
.Join(p=>p.Id, dc.PostTags, (p, pt)=>new{Post = P, PostTag = pt})
.Where(o=>SelectTags.Contains(o.PostTag))
.GroupBy(o=>o.Post, o=>o.PostTag)
.Select(g=>new{Post=>g.Key, Count=>g.Count()})
.Where(o=>o.Count == SelectTags.Count())
.Select(o=>o.Post)
.OrderByDescending(o=>o.DateAdded)
.Take(numPosts)
.Tolist()

注意 - 我刚刚在这里打字,可能不是最佳方式

我在这里做的是我选择
1.选择带标签的标签
2.过滤掉所有记录不在SelectedTags列表中 3.然后按产品分组,制作Enumerable objects个帖子为key(No of Tags)value
4.然后再次使用(Count Of Tags)!= (Count of SelectedTags)

过滤掉所有记录

答案 2 :(得分:0)

如果您有另一个包含所有可用标记的Tag表,您可以考虑使用简单的Count:

var postsIds = (from p in posts
    join t in postTags on p.Id equals t.PostId
    group p by p.Id into grp
    where grp.Count() == tags.Count()
    select grp.Key).ToList();