好的,我有这些POCO的
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Manufacturer { get; set; }
}
public class Offer
{
public int Id { get; set; }
public User Seller { get; set; }
public Product Product { get; set; }
public decimal Price { get; set; }
}
我有许多派生自Product的类,而Offer类的产品属性可以是其中任何一个。
我想定义静态索引,以每个产品的最低价格返回商品,然后按产品类型对其进行过滤。
我到目前为止。
Map = offers => offers.Select(x => new Offer { Product = x.Product, Price = x.Price });
Reduce = results => from r in results
group r by r.Product into g
select new Offer { Product = g.Key , Price = g.Min(x => x.Price) };
这确实有效,并且给了我最低的价格,虽然我认为Map应该只使用Product.Id,而不是整个事情(我只是不知道该怎么做)。
当我查询索引时:
Session.Query<Offer>("BestOffersIndex").Where(offer => offer.Product is DerivedProduct)
它只是忽略了Where条件。
如果我这样做:
Map = offers => offers.Select(x => new OfferIndexResult { ProductType = MetadataFor(x.Product)["Raven-Entity-Name"].ToString(), ProductId = x.Product.Id, Price = x.Price });
Reduce = results => from r in results
group r by r.ProductId into g
select new OfferIndexResult { ProductType = g.FirstOrDefault().ProductType, ProductId = g.Key, Price = g.Min(x => x.Price) };
TransformResults = (database, offers) => from offer in offers
let product = database.Load<Product>(offer.ProductId.ToString())
select new Offer { Product = product, Price = offer.Price };
实时投影中的已加载产品为空,我不知道如何使用ProductType进行过滤。
感谢任何帮助。
答案 0 :(得分:1)
根据评论中的讨论,我对问题有了更好的理解。具体来说,Product
类中的Offer
是 embedded ,它是其他产品的基类。因此,您无法使用我所描述的方法(请参阅编辑),因为在索引Product
时,您无法访问Offer
的元数据。
解决方案是依赖于您的基类将使用$type
属性进行序列化的事实。这是由Json.Net完成的,因为您正在存储一个派生类型的类。序列化的Offer
文档如下所示:
{
"SellerUserId": 1,
"Product": {
"$type": "YourNamespace.TheProductType, YourAssembly",
"Id": 1,
"Name": "product name",
"Manufacturer": "manufacturer"
},
"Price": 10.0
}
要绝对确保$type
始终存在,请将Product
类标记为abstract
,以便所有实际产品都必须是派生类。
因此,在构建索引映射时,您需要访问此字段。您可以使用AsDocument
方法获取它:
Map = offers => from offer in offers
select new
{
Product = offer.Product,
offer.Price,
ProductType = AsDocument(offer.Product)["$type"]
};
当您进行查询并希望按产品类型进行过滤时,您可以获得如下字符串产品类型:
var productType = documentStore.Conventions.GetClrTypeName(typeof(ProductA));
我已将完整的单元测试here放在一起,向您展示如何使用此技术达到您描述的目标。