好的,我有这些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的Product属性可以是它们中的任何一个。
我想定义静态索引,返回每个产品的最低价格的Offers,然后按产品类型过滤它。
我走了这么远。
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。我,不是全部(我只是不知道怎么做)。
当我查询索引时:
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进行过滤。
通过评论中的讨论,我对这个问题有了更好的理解。具体来说,Product
是嵌入在Offer
类中的,是其他产品的基类。因此,您不能使用我描述的方法(参见编辑),因为当您索引Offer
时,您无法访问Product
的元数据。
解决方案是依赖这样一个事实,即您的基类将使用$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));
我在这里把一个完整的单元测试放在一起,向您展示如何使用这种技术来达到您所描述的目标。