>我有一个名为"Posts"的Wyam管道,里面装满了文档。其中一些文档具有Tags
元值,这是一个逗号分隔的标记列表。 例如,假设它有三个文档,元Tags
:
gumby,pokey
gumby,oscar
oscar,kermit
我想要一个新的管道,其中为每个在"帖子"管道中找到的唯一标签填充了一个文档。 这些文档应该在名为 TagName
的元值中具有标记。
因此,上述值应生成一个由四个文档组成的新管道,其TagName
元值为:
gumby
pokey
oscar
kermit
这是我的解决方案。 这在技术上是可行的,但我觉得它效率低下,我很确定一定有更好的方法。
Documents(c => c.Documents["Posts"]
.Select(d => d.String("Tags", string.Empty))
.SelectMany(s => s.Split(",".ToCharArray()))
.Select(s => s.Trim().ToLower())
.Distinct()
.Select(s => c.GetNewDocument(
string.Empty,
new List<KeyValuePair<string, object>>()
{
new KeyValuePair<string, object>("TagName", s)
}
))
)
所以,我打电话给Documents
并通过一个ContextConfig
:
- 从"帖子"中获取文档(我有一个文档集合)
- 选择
Tags
元值(现在我有一个字符串集合) - 将其拆分为逗号(更大的字符串集合)
- 然后修剪和小写(仍然是字符串的集合)
- 消除重复数据(较小的字符串集合)
- 然后为列表中的每个值创建一个新文档,其中包含空正文和字符串的
TagName
值(我应该最终得到一个新文档的集合)
同样,这有效。 但是有更好的方法吗?
这实际上一点也不差 - 这里的部分挑战是将逗号分隔的标记列表转换为可由 LINQ 表达式或类似表达式处理的内容。这部分可能是不可避免的,占你表达式中的 3 行。
也就是说,Wyam 确实在 ToLookup()
扩展方面提供了一些帮助(请参阅本页底部:http://wyam.io/getting-started/concepts)。
下面是它的外观(此代码来自自包含的 LINQPad 脚本,需要进行调整才能在 Wyam 配置文件中使用):
public void Main()
{
Engine engine = new Engine();
engine.Pipelines.Add("Posts",
new PostsDocuments(),
new Meta("TagArray", (doc, ctx) => doc.String("Tags")
.ToLowerInvariant().Split(',').Select(x => x.Trim()).ToArray())
);
engine.Pipelines.Add("Tags",
new Documents(ctx => ctx.Documents["Posts"]
.ToLookup<string>("TagArray")
.Select(x => ctx.GetNewDocument(new MetadataItems { { "TagName", x.Key } }))),
new Execute((doc, ctx) =>
{
Console.WriteLine(doc["TagName"]);
return null;
})
);
engine.Execute();
}
public class PostsDocuments : IModule
{
public IEnumerable<IDocument> Execute(IReadOnlyList<IDocument> inputs, IExecutionContext context)
{
yield return context.GetNewDocument(new MetadataItems { { "Tags", "gumby,pokey" } });
yield return context.GetNewDocument(new MetadataItems { { "Tags", "gumby,oscar" } });
yield return context.GetNewDocument(new MetadataItems { { "Tags", "oscar,kermit" } });
}
}
输出:
gumby
pokey
oscar
kermit
其中很多只是内务管理,以设置虚假的测试环境。您正在寻找的重要部分是:
engine.Pipelines.Add("Tags",
new Documents(ctx => ctx.Documents["Posts"]
.ToLookup<string>("TagArray")
.Select(x => ctx.GetNewDocument(new MetadataItems { { "TagName", x.Key } }))),
// ...
);
请注意,我们仍然需要完成将逗号分隔的标签列表放入数组的工作 - 它只是在"Posts"管道的早期发生。