如何通过单条Core Data查询按指定商品货架分组获取指定区域超市列表
Core Data 查询解决方案:按指定商品货架分组超市
首先明确你的实体关系:
- StoreInventory:记录商品的货架信息,关联超市和食品
- GroceryStore:超市实体,与StoreInventory是一对多关系
- Product:食品实体,与StoreInventory是一对多关系
你的需求是完全可行的,而且不需要创建多余的StoreInventory实体,下面是Objective-C的实现方案:
思路说明
- 先筛选出
Central和Southern区域的目标超市 - 通过Core Data表达式处理分组逻辑:
- 对于售卖"Froot Loops"的超市,用对应商品的货架号作为分组键
- 对于未售卖该商品的超市,用
(No aisle)作为分组键
- 执行分组查询并整理成你期望的结果格式
Objective-C 代码实现
// 获取你的Core Data上下文(根据项目实际情况调整获取方式) NSManagedObjectContext *context = [self managedObjectContext]; // 创建针对GroceryStore实体的查询请求 NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"GroceryStore"]; // 1. 筛选区域:只保留Central和Southern的超市 NSPredicate *regionFilter = [NSPredicate predicateWithFormat:@"storeRegion IN %@", @[@"Central", @"Southern"]]; fetchRequest.predicate = regionFilter; // 2. 构建分组键的表达式 // 筛选当前超市关联的、对应Froot Loops的StoreInventory集合 NSExpression *frootLoopsInventoryExpr = [NSExpression expressionForKeyPath:@"storeInventories.@filteredSet.product.productName == 'Froot Loops'"]; // 获取对应货架号的表达式 NSExpression *aisleExpr = [NSExpression expressionForKeyPath:@"storeInventories.@filteredSet.@distinctUnionOfObjects.aisle"]; // 无该商品时的默认分组键 NSExpression *noAisleExpr = [NSExpression expressionForConstantValue:@"(No aisle)"]; // 条件表达式:如果有Froot Loops的库存则取货架号,否则用默认值 NSExpression *groupKeyExpr = [NSExpression expressionForConditional: [NSExpression expressionForFunction:@"count:" arguments:@[frootLoopsInventoryExpr]] greaterThan:[NSExpression expressionForConstantValue:@0] then:aisleExpr else:noAisleExpr]; // 包装表达式为可查询的属性描述 NSExpressionDescription *groupKeyDesc = [[NSExpressionDescription alloc] init]; groupKeyDesc.name = @"groupKey"; groupKeyDesc.expression = groupKeyExpr; groupKeyDesc.expressionResultType = NSStringAttributeType; // 3. 设置查询的属性、分组规则和结果类型 fetchRequest.propertiesToFetch = @[groupKeyDesc, [NSExpressionDescription expressionDescriptionForSelf]]; fetchRequest.propertiesToGroupBy = @[groupKeyDesc]; fetchRequest.resultType = NSDictionaryResultType; // 4. 执行查询 NSError *error = nil; NSArray *queryResults = [context executeFetchRequest:fetchRequest error:&error]; if (error) { NSLog(@"Core Data 查询错误: %@", error.localizedDescription); return; } // 5. 整理结果为你期望的分组格式 NSMutableDictionary *groupedStores = [NSMutableDictionary dictionary]; for (NSDictionary *resultDict in queryResults) { NSString *groupName = resultDict[@"groupKey"]; // 处理货架号的格式,比如添加"Aisle "前缀 if (![groupName isEqualToString:@"(No aisle)"]) { groupName = [NSString stringWithFormat:@"Aisle %@", groupName]; } GroceryStore *store = resultDict[@"self"]; if (!groupedStores[groupName]) { groupedStores[groupName] = [NSMutableArray array]; } [groupedStores[groupName] addObject:store.storeName]; } // 输出结果(可根据业务需求调整展示逻辑) for (NSString *group in groupedStores.allKeys) { NSLog(@"Group \"%@\"", group); for (NSString *storeName in groupedStores[group]) { NSLog(@" %@", storeName); } }
注意事项
- 请确保你的实体关系名称与代码中一致:比如GroceryStore到StoreInventory的关系名为
storeInventories,如果你的项目中关系名不同,需要对应修改代码中的键路径。 - 该方案通过Core Data的表达式和分组功能直接完成查询,无需为无关联的超市创建无效的StoreInventory实体,完全符合你的要求。
内容的提问来源于stack exchange,提问作者user2592842
相关产品推荐
相关产品推荐

