Search code examples
sortinggrailsmany-to-manygrails-ormtransient

Grails many to many with 3 classes: sorting by the number of relationships


Let's say we have 3 domain classes: 2 classes related with each other through a 3rd class.

Ok, some code:

class A {
     String subject
     String description

     static hasMany = [cs: C]

     static transients = ['numberOfCs']

     Long getNumberOfCs() {
         return cs.size()
     }
}

class B {
     String title
}

class C {
     A objectA
     B objectB

     static belongsTo = [a: A]
}

Pretty clear? I hope so. This work perfectly with my domain.

You can see the transient property numberOfCs, which is used to calculate the number of C instances related to my A object. And it works just fine.

The problem: listing all my A objects, I want to sort them by the number of relationships with C objects, but the transient property numberOfCs cannot be used for the scope.

How can I handle the situation? How can I tell GORM to sort the As list by numberOfCs as it would be a regular (non transient) field?

Thanks in advance.


Solution

  • I'm not sure that Grails' criteria do support this, as you need both to select the A object itself and aggregate by a child objects (C). That means grouping by all the A's fields, which is not done automatically.

    If you only need some fields from A, you can group by them:

    def instances = A.withCriteria {
      projections { 
        groupProperty('subject')
        count('cs', 'cCount')
      }
      order 'cCount'
    }
    

    otherwise you'll need to retrieve only ids and make a second query, like in this question.

    Another way is to use derived properties like described here (not sure it will work though):

    class A {
        static mapping = {
            numberOfCs formula: 'select count(*) from C where c.b_id = id'
        }
    }