簡體   English   中英

CoreData獲取添加基於謂詞的屬性

[英]CoreData fetch adding an attribute based on a predicate

我有以下數據模型(簡化):

WordEntity          ListItemEntity          ListEntity
----------          --------------          ----------
text                                        name
----------          --------------          ----------
listItems <------>> word
                    list <<---------------> items

以及以下基本查詢:

let fetchRequest = NSFetchRequest(entityName: "WordEntity")
let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)

let list = <ListEntity instance>
... do something clever here ...
controller.performFetch(nil)

我需要獲取的結果為每個對象包括inList屬性,如果該WordEntity對象附加到ListItemEntity,而ListItemEntity依次附加到list ,則該屬性為true。 類似於以下謂詞的東西,除了用於創建新屬性而不是過濾提取請求之外:

NSPredicate(format: "ANY listItems.list == %@", list)

我看了NSExpressions,但它們似乎僅用於匯總,不能做謂詞。 SUBQUERY可以做謂詞,但只能用於過濾結果集。 計算出的瞬態屬性可以執行我想要的任何查找,但是它們無法對外部值進行操作...

我希望這很清楚...在此先感謝。

更新:

正如pbasdf建議的那樣,我可以使用獲取的屬性來執行此操作。 我在WordEntity使用謂詞獲取了屬性listItemsInList

(word == $FETCH_SOURCE) AND (list == $FETCHED_PROPERTY.userInfo.list)

然后在代碼中:

let request = NSFetchRequest()
let entity = NSEntityDescription.entityForName("WordEntity", inManagedObjectContext: context)!
request.entity = entity
for property in entity.properties {
    if property.name == "listItemsInList" {
        let list = <ListEntity instance>
        (property as NSFetchedPropertyDescription).userInfo!["list"] = list
    }
}

最后:

if word.listItemsInList.count > 0 {
    ... this is what I was looking for ...
}

這可行。 不幸的是,這是非常低效的。 獲取的屬性始終返回獲取的對象數組,而不是計算值。 他們總是獲取整個對象。 最糟糕的是,它們無法預取,因此檢查表單元格中的屬性意味着每一行都有數據庫命中。 所以我仍然希望有一種更聰明的方法來做到這一點。

經過一番嘗試和錯誤之后,我找到了一個解決方案,該解決方案可以通過一次CoreData獲取來實現您想要的目標,前提是您對實體屬性按“值”返回(即它們將是基礎屬性的副本)感到滿意在一系列字典中。 一種節省的寬限是字典可以包含相關對象的CoreData objectID,因此檢索該對象相對簡單。

訣竅是使用NSExpression,其中包括一個SUBQUERY(用相關的列表名稱替換)和@count。 這是我使用的(抱歉,再次使用Obj-C!):

// First, get an NSAttribute description for each of the attributes we want in our query
NSEntityDescription* entity = [NSEntityDescription entityForName:@"WordEntity" inManagedObjectContext:self.context];
NSAttributeDescription *wordDesc = [entity.attributesByName objectForKey:@"word"];

// Also get an NSExpression description for the object itself
NSExpression *objIDExpression = [NSExpression expressionForEvaluatedObject];
NSExpressionDescription *objIDDescription = [[NSExpressionDescription alloc] init];
[objIDDescription setName: @"cdObjectID"];
[objIDDescription setExpression: objIDExpression];
[objIDDescription setExpressionResultType: NSObjectIDAttributeType];

// Define an expression to count a subquery
NSExpression *countExpression = [NSExpression expressionWithFormat:@"SUBQUERY(listItems,$x,$x.list.listName like %@).@count",@"Animals",nil]; 
// Note, in the above, replace @"Animals" with list.listName for the list of interest

NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName: @"count"];
[expressionDescription setExpression: countExpression];
[expressionDescription setExpressionResultType: NSInteger32AttributeType];

NSFetchRequest* fetch = [NSFetchRequest fetchRequestWithEntityName:@"WordEntity"];
[fetch setPropertiesToFetch:@[wordDesc, objIDDescription, expressionDescription]];
[fetch setResultType:NSDictionaryResultType];
NSArray *myResults = [self.context executeFetchRequest:fetch error:&error];
NSLog(@"myResults: %@",myResults);
// Recover the actual WordEntity object for the first item in myResults:
WordEntity *myWord = (WordEntity *)[self.context objectWithID:[[myResults firstObject] valueForKey:@"cdObjectID"]];

myResults的輸出如下所示。 我的測試數據包括各種單詞,這些單詞包含在名為Animals,Food等的列表中。 狗的筆記數= 1!

    {
    cdObjectID = "0xd000000000040004 <x-coredata://4B6BC796-CAEF-4B0C-9B27-BC6CCDA572C7/WordEntity/p1>";
    count = 0;
    word = Orange;
},
    {
    cdObjectID = "0xd000000000080004 <x-coredata://4B6BC796-CAEF-4B0C-9B27-BC6CCDA572C7/WordEntity/p2>";
    count = 0;
    word = Geranium;
},
    {
    cdObjectID = "0xd0000000000c0004 <x-coredata://4B6BC796-CAEF-4B0C-9B27-BC6CCDA572C7/WordEntity/p3>";
    count = 0;
    word = Banana;
},
    {
    cdObjectID = "0xd000000000100004 <x-coredata://4B6BC796-CAEF-4B0C-9B27-BC6CCDA572C7/WordEntity/p4>";
    count = 1;
    word = Dog;
},
    {
    cdObjectID = "0xd000000000140004 <x-coredata://4B6BC796-CAEF-4B0C-9B27-BC6CCDA572C7/WordEntity/p5>";
    count = 0;
    word = Apple;
},
    {
    cdObjectID = "0xd000000000180004 <x-coredata://4B6BC796-CAEF-4B0C-9B27-BC6CCDA572C7/WordEntity/p6>";
    count = 1;
    word = Elephant;
}, ....

我不知道如何將性能與其他解決方案進行比較!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM