流索引查询结果异常

本文关键字:异常 结果 查询 索引 | 更新日期: 2023-09-27 18:13:56

我们目前正在尝试使用Task<IAsyncEnumerator<StreamResult<T>>> StreamAsync<T>(IQueryable<T> query, CancellationToken token = null),遇到一些问题。

我们的文档看起来像:

public class Entity
{
    public string Id { get; set; }
    public DateTime Created { get; set; }
    public Geolocation Geolocation { get; set; }
    public string Description { get; set; }
    public IList<string> SubEntities { get; set; }
    public Entity()
    {
      this.Id = Guid.NewGuid().ToString();
      this.Created = DateTime.UtcNow;
    }
}

我们有一个视图模型,它也是我们索引的模型:

public class EntityViewModel
{
    public string Id { get; set; }
    public DateTime Created { get; set; }
    public Geolocation Geolocation { get; set; }
    public string Description { get; set; }
    public IList<SubEntity> SubEntities { get; set; }
}

当然,还有从视图模型继承结果类型的索引,以使子实体能够正确映射和输出,同时支持添加搜索特性,如全文等:

public class EntityWithSubentitiesIndex : AbstractIndexCreationTask<Entity, EntityWithSubentitiesIndex.Result>
{
    public class Result : EntityViewModel
    {
         public string Fulltext { get; set; }
    }
    public EntityWithSubentitiesIndex ()
    {
        Map = entities => from entity in entities
                select new
                {
                    Id = entity.Id,
                    Created = entity.Created,
                    Geolocation = entity.Geolocation,
                    SubEntities = entity.SubEntities.Select(x => LoadDocument<SubEntity>(x)),
                    Fulltext = new[]
                    {
                        entity.Description
                    }.Concat(entity.SubEntities.Select(x => LoadDocument<SubEntity>(x).Name)),
                    __ = SpatialGenerate("__geolokation", entity.Geolocation.Lat, entity.Geolocation.Lon)
                };
            Index(x => x.Created.Date, FieldIndexing.Analyzed);
            Index(x => x.Fulltext, FieldIndexing.Analyzed);
            Spatial("__geolokation", x => x.Cartesian.BoundingBoxIndex());
        }
}

最后我们像这样查询:

var query = _ravenSession.Query<EntityWithSubentitiesIndex.Result, EntityWithSubentitiesIndex>()
                .Customize(c =>
                {
                    if (filter.Boundary == null) return;
                    var wkt = filter.Boundary.GenerateWkt().Result;
                    if (!string.IsNullOrWhiteSpace(wkt))
                    {
                        c.RelatesToShape("__geolokation", wkt, SpatialRelation.Within);
                    }
                })
                .AsQueryable();
// (...) and several other filters here, removed for clarity
var enumerator = await _ravenSession.Advanced.StreamAsync(query);
var list = new List<EntityViewModel>(); 
while (await enumerator.MoveNextAsync())
{
    list.Add(enumerator.Current.Document);
}

当这样做时,我们会得到以下异常:

系统。InvalidOperationException:查询结果类型为"实体"但你期望得到类型为"结果"的结果。如果你想返回一个投影,你应该使用. projectfrommindexfieldsinto()(用于查询)或.在调用之前选择字段()(对于DocumentQuery).ToList () .

根据文档,流式API应该支持通过索引进行流式传输,同时通过IQueryable进行查询。

如何解决这个问题,同时仍然使用索引和流API:

  1. 防止必须通过正常查询页面,以绕过默认页面大小
  2. 防止在查询
  3. 时一次加载一个子实体

提前感谢!

流索引查询结果异常

尝试使用:

.As<Entity>()

(或.OfType<Entity>())。

这是一个使用"TestIndex"的简单流查询,这是一个实体Test的索引,我使用TestIndex.Result看起来像你的查询。请注意,这实际上不是查询将返回的内容,它只是在那里,以便您可以编写类型化查询(即。.Where(x => x.SomethingMapped == something))

var queryable = session.Query<TestIndex.Result, TestIndex>()
                        .Customize(c =>
                        {
                            //do stuff
                        })
                        .As<Test>();
var enumerator = session.Advanced.Stream(queryable);
while (enumerator.MoveNext())
{
    var entity = enumerator.Current.Document;
}

如果您想从索引中检索值,而不是从被索引的实际实体中检索值,您必须将这些存储为字段,然后将它们投影到与映射属性匹配的"视图模型"中。这可以通过在查询中使用.ProjectFromIndexFieldsInto<T>()来完成。索引中存储的所有字段都将映射到您指定的模型。

希望这有助于(和有意义)!

编辑:更新了一个,对我来说,ProjectFromIndexFieldsInto<T>()使用的流媒体API的工作示例,返回超过128条记录。

using (var session = store.OpenAsyncSession())
{
    var queryable = session.Query<Customers_ByName.QueryModel, Customers_ByName>()
        .Customize(c =>
        {
            //just to do some customization to look more like OP's query
            c.RandomOrdering();
        })
        .ProjectFromIndexFieldsInto<CustomerViewModel>();
    var enumerator = await session.Advanced.StreamAsync(queryable);
    var customerViewModels = new List<CustomerViewModel>();
    while (await enumerator.MoveNextAsync())
    {
        customerViewModels.Add(enumerator.Current.Document);
    }
    Console.WriteLine(customerViewModels.Count); //in my case 504
}

上面的代码对我来说效果很好。索引映射了一个属性(名称),并存储了该属性。这是最新的稳定版本(3.0.800)

正如@nicolai-heilbuth在@jens-pettersson回答的评论中所说,这似乎是版本3以后RavenDB客户端库中的一个bug。

Bug报告在这里提交:http://issues.hibernatingrhinos.com/issue/RavenDB-3916