Fetching Child Sum from Core Data

Fetching child sum from Core Data

This is probably most easily done using Key Value Coding "collection operators" (see here) rather than a fetch. For each person:

let name = person.name
let totalIncome = person.valueForKeyPath("salary.@sum.income")
let totalLoans = person.valueForKeyPath("loans.@sum.amount")

If performance is an issue, you might improve things by amending the fetch request (for the Person objects) to "prefetch" the related Salary and Bills objects:

fetchRequest.relationshipKeyPathsForPrefetching = ["salary", "loans"]

Alternatively, it is possible to retrieve the required information all in one fetch, though I do not recommend it because it requires changing the fetchRequest to return an array of dictionaries rather than an array of NSManagedObjects. This makes subsequent processing (eg. populating your table view) more difficult.

// Define NSExpression and NSExpressionDescription for the total income
let incomeED = NSExpressionDescription()
incomeED.expression = NSExpression(forKeyPath: "salary.@sum.income")
incomeED.name = "totalIncome"
incomeED.expressionResultType = .Integer64AttributeType
// Define NSExpression and NSExpressionDescription for the total amount
let amtED = NSExpressionDescription()
amtED.expression = NSExpression(forKeyPath: "loans.@sum.amount")
amtED.name = "totalLoans"
amtED.expressionResultType = .Integer64AttributeType
// specify attributes and expressions to fetch
fetchRequest.propertiesToFetch = ["name", incomeED, amtED]
// specify dictionary return type (required to process NSExpressions)
fetchRequest.resultType = .DictionaryResultType

The result of the fetch will be an array of dictionaries; each dictionary will have keys "name", "totalIncome" and "totalLoans" (with corresponding values).

Fetching child count from Core Data

The following should work

let totalIncome = item.value(forKeyPath: "attribute.@sum.income") as? Int ?? 0

Sum on child object while displaying parent object - Core Data

First of all, you shouldn't think of entities being in a parent-child/tree structure unless your object graph actively enforces such a structure. In most cases it won't and any two entities are structural equals. That appears to be the case with your 'Customer' and 'Order' entities.

It's an important concept to grasp because unlike a conventional tree-structure, in a Core Data data graph, you can enter the graph at any instance of any entity and walk the relationships in any direction e.g. You don't have to always fetch a Customer object to start, you can if needed fetch a Order object just as easily.

In this particular case you are fetching Customer objects and you want to find all associated Order objects. Your data model should look something like this:

Customer{
name:string
orders<-->>Order.customer
}

Order{
item:string
cost:number
customer<<-(required)->Customer.orders
}

Now, every time you create a new Orderobject you automatically link it the appropiate Customer object. When you fetch any particular Customer object all it's related Order objects are available in the Customer.orders relationship.

If you wanted to sum the cost of all a customer's orders, you could use a collection operator like so:

NSNumber *orderSum=[Customer.order valueForKeyPath:@"@sum.orders.cost"];

Relationships are very important to Core Data.

Core Data sum in relationship

Your using the @sum with the correct syntax. Most likely, you have just got another part of the keypath wrong e.g. "expenses" instead of "expense". Alternatively, you may be fetching the wrong entity.

If all you want to do is fetch this sum, do an attribute fetch and set your return type to dictionary. (See NSFetchRequest and Core Data Programming Guide) docs for details. That returns an array of dictionaries whose sole key is the attribute name and whose sole value is the value of selected attribute of one managed object. It's faster and uses fewer resources than fetching full objects.

When loading an NSManagedObject from Core Data, do I get it's children for free?

When seeing your AlarmMO model, you can just fetch your AlarmMO model which will hold the list of NotificationUuidMO in notificationUuidChildren Set. So there is no need to fetch NotificationUuidMO separately.

And AlarmMO to NotificationUuidMO is one to many relationship. So you can get notificationUuidChildren from AlarmMO and alarmParent from NotificationUuidMO.

To add NotificationUuidMO to notificationUuidChildren Set, you can use Core-Data generated accessors given in extension AlarmMO.

Example:

let notificationUuid = NotificationUuidMO....
let alarmMO = AlarmMO....

alarmMO.addToNotificationUuidChildren(notificationUuid)//Here your notificationUuid will be added to `notificationUuidChildren` Set and `alarmParent` of your `notificationUuid` will be automatically assigned to `alarmMO`.

Swift - CoreData NSPredicate - Fetch Children of parent

The key path used in the fetch request must match the actual name
of the Core Data relationship, in your case "agendaEvents",
there is no implicit "parent" relationship:

fetchRquest.predicate = NSPredicate(format: "agendaEvents == %@", event)

Even better, use #keyPath and the %K expansion

fetchRquest.predicate = NSPredicate(format: "%K == %@",
#keyPath(AgendaDate.agendaEvents), event)

so the that compiler checks the validity of the key path.
This helps to avoid using unknown key paths or typos.

Note that a better relationship name would be "agendaEvent"
or just "event", with the singular form for a to-one relationship.

Core Data: fetch request for fetching entities in a one-many-one relationship

I got lucky and found this answer
NSPredicate acting strange in NSFetchedResultsController

The question was worded differently, which is why it took awhile for me to find it. Basically, the predicate I'm looking for is of the following format:

[NSPredicate predicateWithFormat:@"SUBQUERY(parent, $x, $x.grandparent == %@).@count != 0", grandParent];

IOS/Objective C/Core Data: Sum all the values for an attribute from query

You can use key-value coding:

NSNumber *orderTotal = [arrayWhoseSumIsToBeCalculated valueForKeyPath:@"@sum.self"];


Related Topics



Leave a reply



Submit