问题描述
我有以下对象:
public class Post
{
public string Id { get; set; }
public string Url { get; set; }
public Profile Profile { get; set; }
public DateTime CreatedOn { get; set; }
[JsonProperty("@Metadata")]
public Metadata Metadata { get; set; }
}
public class Metadata
{
[JsonProperty("@attachments")]
public List<AttachmentName> Attachments { get; set; }
}
当我尝试执行以下查询时:
return await query.Select(x => new Repository.SummaryPost
{
Id = x.Id,CreatedOn = x.CreatedOn,Url = x.Url,AttachmentNames = x.Metadata.Attachments.Select(x => x.Name),Profile = new Repository.SummaryProfile
{
Id = x.Profile.Id,Name = x.Profile.Name,Url = x.Profile.Url,Source = new Repository.SummarySource
{
Id = x.Profile.source.Id,Name = x.Profile.source.Name,Url = x.Profile.source.Url
}
}
}).ToListAsync()
它尝试运行以下 RQL:
from 'Posts' as x
order by CreatedOn desc
select {
Id : id(x),CreatedOn : x.CreatedOn,Url : x.Url,AttachmentNames : x.@Metadata.@attachments.map(function(x){return x.Name;}),Profile :
{
Id:x.Profile.Id,Name:x.Profile.Name,Url:x.Profile.Url,Source:{
Id:x.Profile.source.Id,Name:x.Profile.source.Name,Url:x.Profile.source.Url
}
}
}
limit $p0,$p1
这是无效的,并抛出以下错误:
---> esprima.ParserException: Line 5: Unexpected token ILLEgal
at esprima.Scanner.ThrowUnexpectedToken(String message)
at esprima.Scanner.ScanPunctuator()
at esprima.JavaScriptParser.NextToken()
at esprima.JavaScriptParser.ParseLeftHandSideExpressionAllowCall()
at esprima.JavaScriptParser.InheritCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParseUpdateExpression()
at esprima.JavaScriptParser.ParseUnaryExpression()
at esprima.JavaScriptParser.InheritCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParseExponentiationExpression()
at esprima.JavaScriptParser.InheritCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParseBinaryExpression()
at esprima.JavaScriptParser.InheritCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParseConditionalExpression()
at esprima.JavaScriptParser.ParseAssignmentExpression()
at esprima.JavaScriptParser.InheritCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParSEObjectProperty(Token hasProto)
at esprima.JavaScriptParser.ParSEObjectinitializer()
at esprima.JavaScriptParser.InheritCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParsePrimaryExpression()
at esprima.JavaScriptParser.InheritCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParseLeftHandSideExpressionAllowCall()
at esprima.JavaScriptParser.InheritCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParseUpdateExpression()
at esprima.JavaScriptParser.ParseUnaryExpression()
at esprima.JavaScriptParser.InheritCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParseExponentiationExpression()
at esprima.JavaScriptParser.InheritCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParseBinaryExpression()
at esprima.JavaScriptParser.InheritCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParseConditionalExpression()
at esprima.JavaScriptParser.ParseAssignmentExpression()
at esprima.JavaScriptParser.IsolateCoverGrammar[T](Func`1 parseFunction)
at esprima.JavaScriptParser.ParseExpression()
at esprima.JavaScriptParser.ParseReturnStatement()
at esprima.JavaScriptParser.ParseStatement()
at esprima.JavaScriptParser.ParseStatementListItem()
at esprima.JavaScriptParser.ParseScript(Boolean strict)
at Raven.Server.Documents.Queries.QueryMetadata.HandleSelectFunctionBody(BlittableJsonReaderObject parameters) in C:\Builds\RavendB-Stable-5.1\51018\src\Raven.Server\Documents\Queries\QueryMetadata.cs:line 601
这是由于 x.@Metadata.@attachments
,如果我在没有 Raven Studio 元数据的情况下运行相同的查询,它运行没有问题。
我想知道我是否遗漏了什么,或者是否有适当的方法来实现这一点。
解决方法
经过一些尝试和错误尝试后,我可以弄清楚如何正确地做到这一点。
首先,不需要使用那些 JsonProperty
表示法。其次,要正确查询元数据,我们需要使用 RQL 中的 getMetadata(x)
,并且要生成该查询,我们需要修改该 LINQ 以使用 RavenQuery.Metadata(x)
。像这样:
return await query.Select(x => new Repository.SummaryPost
{
Id = x.Id,CreatedOn = x.CreatedOn,Url = x.Url,Metadata = RavenQuery.Metadata(x)["@attachments"],Profile = new Repository.SummaryProfile
{
Id = x.Profile.Id,Name = x.Profile.Name,Url = x.Profile.Url,Source = new Repository.SummarySource
{
Id = x.Profile.Source.Id,Name = x.Profile.Source.Name,Url = x.Profile.Source.Url
}
}
}).ToListAsync();
这将生成以下 RQL:
from 'Posts' as x
order by CreatedOn desc
select {
Id : id(x),CreatedOn : x.CreatedOn,Url : x.Url,Metadata : getMetadata(x)["@attachments"],Profile : {
Id:x.Profile.Id,Name:x.Profile.Name,Url:x.Profile.Url,Source:{
Id:x.Profile.Source.Id,Name:x.Profile.Source.Name,Url:x.Profile.Source.Url
}
}
}
limit $p0,$p1
获取文档列表和附件列表。
通过在 LINQ 查询中添加以下行,我们甚至可以更具体地只查询附件名称:
AttachmentNames = ((IEnumerable<AttachmentName>) RavenQuery.Metadata(x)["@attachments"]).Select(x => x.Name)
它将为 AttachmentNames
字段生成以下 RQL:
AttachmentNames : getMetadata(x)["@attachments"].map(function(x){return x.Name;})
仅查询名称。