CoreData sort results by number of matching relationships

53 views Asked by At

I'm not able to figure out how to sort results from CoreData based on the number of matching relationships.

Concrete situation:

I have Recipe(s) that have one or more RecipeIngredient(s). I have a search interface where I can select multiple Ingredient(s) and want to get back Recipe(s) ordered by how many RecipeIngredient(s) match my selection. Basically I want to find the recipes with the highest number of matching ingredients.

CoreData schema:

enter image description here

Here is what I've done until now, (sort descriptor is just a default until I figure out how to handle this):

    func searchRecipes(
        searchRequest: RecipeSearchRequest
    ) -> [CDRecipe] {
        let fetchRequest: NSFetchRequest<CDRecipe> = CDRecipe.fetchRequest()
        var predicates: [NSPredicate] = []
        if searchRequest.searchString != "" {
            predicates.append(NSPredicate(format: "title CONTAINS %@", searchRequest.searchString.lowercased()))
        }
        if searchRequest.savedOnly {
            predicates.append(NSPredicate(format: "saved == %@", "true"))
        }

// HERE
        if !searchRequest.includedIngredientIDs.isEmpty {
            predicates.append(NSPredicate(format: "ANY ingredients.ingredient.identifier IN %@", searchRequest.includedIngredientIDs))
        }
        fetchRequest.predicate = NSCompoundPredicate(type: .and, subpredicates: predicates)
        
        let sortDescriptor = NSSortDescriptor(keyPath: \CDRecipe.title, ascending: true)
        
        
        fetchRequest.sortDescriptors = [sortDescriptor]
        fetchRequest.fetchLimit = searchRequest.limit
        do {
            let recipes = try coreDataStack.managedObjectContext.fetch(fetchRequest)
            return recipes
        } catch {
            print(error.localizedDescription)
            return []
        }
    }

I have also considered pulling all the recipes in my database and doing this sorting in memory. However I have 10K+ recipes and will have more in the future so doing this will would be highly inefficient.

0

There are 0 answers