无法在 RavenDB 上查询附件

Can't query attachments on RavenDB

我正在尝试查询文档以及 RavenDB 上的附件列表。

我有以下对象:

   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.1018\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;})

仅查询名称。