這裏有幾個選項。您可以在Item實體上存儲CategoryId和CategoryName。這當然會導致重複的數據(如果您仍然需要存儲類別實體),但「存儲便宜」是近來流行的術語。缺點是您需要更新給定類別的每個Item文檔如果類別名稱更改以保持一致。一個好處是你需要做更少的工作來獲得你想要的結果。
如果您還在商品上存儲商品類別名稱,那麼您不需要特殊的索引來處理第一個商品列表,只需查詢商品並返回您所需的商品。對於第二個列表,您需要在分類上的Item實體上創建Map/Reduce索引。
但是,如果您需要使用您提供的數據結構,有幾種解決方法。首先,真的不建議在索引定義中使用LoadDocument,尤其不要在select語句中使用LoadDocument。這可能會對索引性能產生負面影響。
相反,只指數還需要在查詢(或使用自動索引),然後使用一個結果變壓器從相關文件中讀取信息的屬性:
public class ItemCategoryTransformer : AbstractTransformerCreationTask<Item>
{
public ItemCategoryTransformer()
{
TransformResults = results => from item in results
let category = LoadDocument<Category>(item.CategoryId)
select new ItemCategoryViewModel
{
Name = item.Name,
CategoryName = category.Name
};
}
}
public class ItemCategoryViewModel
{
public string Name { get; set; }
public string CategoryName { get; set; }
}
您可以使用該變壓器具有查詢對項目實體:
using (var session = documentStore.OpenSession())
{
var items = session.Query<Item>()
.TransformWith<ItemCategoryTransformer, ItemCategoryViewModel>()
.ToList();
}
至於第二個列表,仍然使用你的數據結構,你必須使用一些東西。首先,一個Map/Reduce的價格指數比項目,按類別編號分組:
public class Category_Items_Count : AbstractIndexCreationTask<Item, Category_Items_Count.Result>
{
public class Result
{
public string CategoryId { get; set; }
public int Count { get; set; }
}
public Category_Items_Count()
{
Map = items => from item in items
select new Result
{
CategoryId = item.CategoryId,
Count = 1
};
Reduce = results => from result in results
group result by result.CategoryId
into c
select new Result
{
CategoryId = c.Key,
Count = c.Sum(x => x.Count)
};
}
}
但是當你只擁有的CategoryId的項目實體,你必須使用一個類似的變壓器作爲第一個列表:
public class CategoryItemsCountTransformer : AbstractTransformerCreationTask<Category_Items_Count.Result>
{
public CategoryItemsCountTransformer()
{
TransformResults = results => from result in results
let category = LoadDocument<Category>(result.CategoryId)
select new CategoryItemsCountViewModel
{
CategoryName = category.Name,
NumberOfItems = result.Count
};
}
}
public class CategoryItemsCountViewModel
{
public string CategoryName { get; set; }
public int NumberOfItems { get; set; }
}
最後,查詢這樣的:
using (var session = documentStore.OpenSession())
{
var items = session.Query<Category_Items_Count.Result, Category_Items_Count>()
.TransformWith<CategoryItemsCountTransformer, CategoryItemsCountViewModel>()
.ToList();
}
正如你所看到的,有這取決於你使用的是什麼數據結構,做工相當的差別需要。如果您直接在項目實體上存儲了類別名稱,則不需要任何結果轉換器就可以實現您之後的結果(您只需要一個Map/Reduce索引)。
但是,結果變換器在服務器端執行,並且只在請求時執行,而不是在每次索引發生時執行的索引內部使用LoadDocument。另外,也可能是爲什麼不建議在索引定義中使用LoadDocuments,因此索引中LoadDocument引用的文檔的每次更改都會導致該索引必須重寫。這可能會導致索引引擎的很多工作。
最後,回答最後一個問題:爲什麼在查詢時出現異常:由於索引的實際返回類型是索引的文檔(在本例中爲Item)。要使用別的東西,你需要將你的結果投影到別的東西上。這可以通過在查詢中使用「.As()」來完成:
Item_WithCategory.Result[] all;
using (var session = DocumentStoreHolder.Store.OpenSession())
{
all = session.Query<Item_WithCategory.Result, Item_WithCategory>()
.As<Item_WithCategory.Result>()
.ToArray();
}
很長的帖子,但希望它有幫助!
你能解釋爲什麼你需要兩個列表嗎? –