_forRelation (opts, def, fn, thisArg) {
    const relationName = def.relation
    let containedName = null
    let index
    opts || (opts = {})
    opts.with || (opts.with = [])

    if ((index = utils._getIndex(opts.with, relationName)) >= 0) {
      containedName = relationName
    } else if ((index = utils._getIndex(opts.with, def.localField)) >= 0) {
      containedName = def.localField
    }

    if (opts.withAll) {
      fn.call(thisArg, def, {})
      return
    } else if (!containedName) {
      return
    }
    const optsCopy = {}
    utils.fillIn(optsCopy, def.getRelation())
    utils.fillIn(optsCopy, opts)
    optsCopy.with = opts.with.slice()
    optsCopy._activeWith = optsCopy.with.splice(index, 1)[0]
    optsCopy.with.forEach(function (relation, i) {
      if (
        relation &&
        relation.indexOf(containedName) === 0 &&
        relation.length >= containedName.length &&
        relation[containedName.length] === '.'
      ) {
        optsCopy.with[i] = relation.substr(containedName.length + 1)
      } else {
        optsCopy.with[i] = ''
      }
    })
    fn.call(thisArg, def, optsCopy)
  }
Recursively iterates over relations found in `opts.with`.

@method utils._forRelation
@param {object} opts Configuration options.
@param {Relation} def Relation definition.
@param {Function} fn Callback function.
@param {*} [thisArg] Execution context for the callback function.
@private
@since 3.0.0