【问题标题】:Can't query attachments on RavenDB无法在 RavenDB 上查询附件
【发布时间】:2021-04-11 00:43:22
【问题描述】:

我正在尝试查询文档以及 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.1\51018\src\Raven.Server\Documents\Queries\QueryMetadata.cs:line 601

这是由于x.@metadata.@attachments 如果我在 Raven Studio 上运行没有元数据的相同查询,它运行没有问题。

我想知道我是否遗漏了什么,或者是否有适当的方法来实现。

【问题讨论】:

    标签: c# ravendb


    【解决方案1】:

    经过一些尝试和错误尝试,我可以弄清楚如何正确地做到这一点。

    首先,不需要使用那些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;})
    

    仅查询名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多