我正在尝试解决以下LINQ查询:
public JsonResult SearchNodesByTags(string[] tags)
{
var nodes = _DbContext.Nodes.
Where(n => n.Tags.All(t => tags.Contains(t.DisplayName)))
.Select(n => new {n.NodeNativeId, n.NodeName, n.NodeClass.ClassName})
.ToList();
return Json(nodes);
}
查询返回与标记无关的单个节点。我想要它做的是返回任何包含所有标签的节点。
答案 0 :(得分:2)
.Where(n => n.Tags.All(t => tags.Contains(t.DisplayName)))
目前的构建方式,您最终只会得到Node
,其中 Node.Tags
中的每个标记都在{{1}中有一个名称白名单,其中包含没有标记的tags
。
您可能希望在子集上使用here的答案:
Node
_DbContext.Nodes
.Where(n => !tags.Except(n.Tags.Select(t => t.DisplayName)).Any())
.Select(...
包含不在set1.Except(set2)
set1
元素
如果set2
包含!set1.Except(set2).Any() == true
的每个元素,则set2
修改强>
评论中指出,使用Except可能会产生有问题的查询,因此我认为另一种选择是从数据库中获取超集,并进一步过滤应用程序中的对象:
set1
修改2
我刚刚看到另一个可能适合您的here,但它要求_DbContext.Nodes
// filter nodes with any of the input tags
.Where(n => n.Tags.Any(t => tags.Contains(t.DisplayName)))
// select the information required
.Select(n => new {
n.NodeNativeId,
n.NodeName,
ClassName = n.NodeClass.ClassName,
TagNames = n.Tags.Select(t => t.DisplayName) })
// materialize super set with database
.ToList()
// filter so that only nodes with all tags remain
.Where(n => !tags.Except(n.TagNames).Any())
// produce result in anonymous class
.Select(n => new { n.NodeNativeId, n.NodeName, n.ClassName })
.ToList();
唯一 ,因为它可能会失败您有多个具有相同Tag.DisplayName
的标签:
DisplayName