如何按匹配标签的数量对图像列表进行排序?



我正在尝试进行查询以根据标签对图像进行排序。数据组织方式如下:

public class Image
{
public int Id { get; set; }
public List<ImageTag> Tags { get; }
// Some more properties
}
public class ImageTag
{
public int Id { get; set; }
public int ImageId { get; set; }
public string Tag { get; set; }
public Image Image { get; set; }
}

控制器方法接收一个名为csvTags的逗号分隔字符串,可以是"花,植物,水仙花"之类的内容。

预期的结果将是一个列表,其中包含所有三个单词作为标签的图像将位于顶部,然后按匹配标签的数量向下下降。

这是我到目前为止所拥有的:

// Transfer the CSV-data into a List<string>:
List<string> tagsList = csvTags.Split(",").ToList();
// Get those tags from the db, and include the related image of each tag.
// Since a tag can be present on multiple images, this list will likely contain several
// instances of each tag.
List<ImageTag> tags = await db.ImageTags
.Include(i => i.Image)
.Where(t => tagsList.Contains(t.Tag))
.ToListAsync().ConfigureAwait(false);
// Use the list of tags to make a list of images:
List<Image> images = new List<Image>();
foreach (ImageTag tag in tags)
{
// Need some magic here...
// Sort the list by count of tags, and .Distinct() it.
images.Add(tag.Image);
}

实际上,如果可能的话,我想避免foreach部分。

更新

我接受了Tieson的回答,但有点太早了,没有测试它。事实证明,它毕竟不起作用。我收到此错误消息:

InvalidOperationException: LINQ 表达式 'DbSet .其中(w0 => EF.属性>((实体整形表达式: 实体类型:网页内容图像 值缓冲区表达式: (ProjectionBindingExpression: EmptyProjectionMember( 可为空:假 (, "Id"( != null && EF.属性>((实体整形表达式: 实体类型:网页内容图像 值缓冲区表达式: (ProjectionBindingExpression: EmptyProjectionMember( 可为空:假 (, "id"( == EF。属性>(w0, "图像 ID"(( .计数(w0 => __csvTags_0.包含( 值:w0。标记 比较类型:当前文化忽略案例(('无法翻译。以可翻译的形式重写查询,或通过插入对 AsEnumerable((、AsAsyncEnumerable((、ToList(( 或 ToListAsync(( 的调用来显式切换到客户端评估。有关详细信息,请参阅 https://go.microsoft.com/fwlink/?linkid=2101038。

由于以下行,查询无法转换为 SQL 查询:

Matches = m.Tags.Count(n => tagsList.Contains(n.Tag))

如何重写?

更新 2

在内存中集合上运行新查询的工作原理是:

List<WebContentsImage> unsortedImages = 
await db.WebContentsImages.Include(t => t.Tags).ToListAsync().ConfigureAwait(false);
List<WebContentsImage> images = unsortedImages
.Select(m => new
{
Image = m,
Matches = m.Tags.Count(n => csvTags.Contains(n.Tag, StringComparison.CurrentCultureIgnoreCase))
})
.Where(m => m.Matches > 0)
.OrderByDescending(m => m.Matches)
.Select(m => m.Image)
.ToList();

如果不构建类似的数据库进行查询,很难验证,但这样的事情应该有效:

var result = db.Images
.Include(m => m.Tags)
.Select(m => new
{
Image = m,
Matches = m.Tags.Count(n => tagsList.Any(o => o == n.Tag))
})
.Where(m => m.Matches > 0)
.OrderByDescending(m => m.Matches)
.Select(m => m.Image)
.ToList();

这应该会得到一个图像对象列表,按与任何搜索词匹配的关联标签的数量排序。如果你想要匹配的数量,省略最后一个 Select((:

var result = db.Images
.Include(m => m.Tags)
.Select(m => new
{
Image = m,
Matches = m.Tags.Count(n => tagsList.Any(o => o == n.Tag))
})
.Where(m => m.Matches > 0)
.OrderByDescending(m => m.Matches)
.ToList();

这将返回具有 Image 属性和 Match 属性的匿名/动态对象。

最新更新