Note that there are some explanatory texts on larger screens.

plurals
  1. POFiltering many-to-many count expression using existing subquery
    primarykey
    data
    text
    <p>In my app, I have a many-to-many relationship between tags and links as follows :</p> <pre><code>Tags &lt;&lt;--&gt;&gt; Links </code></pre> <p>I am trying to return a list of the tags that relate to links that have the currently active tags, but are not included in the active tags. </p> <p>I also want to obtain a count of the number of links that have the 'other' tags, which needs to be limited by the active tags.</p> <p>Using the below, I have been able to return the 'other' tags and a count of links, but the count returned is of all links for each tag.</p> <p>I would like to be able to count the links using a similar approach to the one I'm using to build the subquery, but am struggling to get it to work. I have tried using the subquery generated in the count NSExpression, but this errors when the subquery is evaluated.</p> <pre><code>// Test array of tag names self.activeTagArray = [@[@"tag1", @"tag2"] mutableCopy]; NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[Tag entityName]]; // We want to exclude the tags that are already active NSPredicate *activeTagsPredicate = [NSPredicate predicateWithFormat:@"NOT ANY name IN %@", self.activeTagArray]; // Build subquery string to identify links that have all of the active tags in their tag set NSString __block *subquery = @"SUBQUERY(links, $link, "; [self.activeTagArray enumerateObjectsUsingBlock:^(id tagName, NSUInteger index, BOOL *stop) { if (index == self.activeTagArray.count - 1) { subquery = [subquery stringByAppendingString:[NSString stringWithFormat:@"SUBQUERY($link.tags, $tag, $tag.name = '%@') != NULL", tagName]]; } else { subquery = [subquery stringByAppendingString:[NSString stringWithFormat:@"SUBQUERY($link.tags, $tag, $tag.name = '%@') != NULL AND ", tagName]]; } }]; subquery = [subquery stringByAppendingString:@") != NULL"]; NSLog(@"Subquery : %@", subquery); NSPredicate *noTagsPredicate = [NSPredicate predicateWithFormat:subquery]; // Create a predicate array NSArray *predicateArray = @[noTagsPredicate, activeTagsPredicate, userPredicate]; NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicateArray]; fetchRequest.predicate = compoundPredicate; fetchRequest.relationshipKeyPathsForPrefetching = @[@"links"]; // Set up the count expression NSExpression *countExpression = [NSExpression expressionForFunction: @"count:" arguments:@[[NSExpression expressionForKeyPath: @"links.href"]]]; NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; expressionDescription.name = @"counter"; expressionDescription.expression = countExpression; expressionDescription.expressionResultType = NSInteger32AttributeType; fetchRequest.propertiesToFetch = @[@"name", expressionDescription]; // Sort by the tag name NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptor]; fetchRequest.resultType = NSDictionaryResultType; NSError *error = nil; NSArray *resultsArray = [self.managedObjectContext executeFetchRequest:fetchRequest error:&amp;error]; if (error) { NSLog(@"Error : %@", [error localizedDescription]); } NSMutableArray *allTags = [[NSMutableArray alloc] init]; for (NSDictionary *tagDict in resultsArray) { NSLog(@"Tag name : %@, Link Count : %@", tagDict[@"name"], tagDict[@"counter"]); [allTags addObject:tagDict[@"name"]]; } [allTags addObjectsFromArray:self.activeTagArray]; </code></pre> <p>Any help with this would be greatly appreciated!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload