我有以下数据模型(简化):
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建议的那样。我在listItemsInList
上有一个带谓词的获取属性WordEntity
:
(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 ...
}
这很有效。不幸的是,效率非常低。获取的属性始终返回已获取对象的数组,而不是计算值。他们总是拿取整个对象。最糟糕的是,它们不能预先获取,因此检查表格单元格中的属性意味着每行都有数据库命中。所以我仍然希望有一个更聪明的方法。
答案 0 :(得分:0)
经过一些试验和错误后,我找到了一个解决方案,只要您对实体的属性被返回&#34;按值&#34,就可以通过单个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的输出如下所示。我的测试数据包括我在名为Animal,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;
}, ....
我不知道如何将性能与其他解决方案进行比较!