流索引查询结果异常
本文关键字:异常 结果 查询 索引 | 更新日期: 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:
- 防止必须通过正常查询页面,以绕过默认页面大小
- 防止在查询 时一次加载一个子实体
提前感谢!
尝试使用:
.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