lucid-mongo icon indicating copy to clipboard operation
lucid-mongo copied to clipboard

Different behavior when using find() on related documents

Open franciscosucre opened this issue 7 years ago • 2 comments

Hello again @duyluonglc , i found an interesting detail, the behavior of the models if i use find is differente if i search them with where and fetch.

My Models:

class Contact extends UserOwnedModel {
  group() {
    return this.belongsTo('App/Models/Group')
  }

  static get objectIDs() {
    var list = super.objectIDs
    return list.concat([
      'group_id'
    ])
  }
}

class Segmentation extends UserOwnedModel {
  
  filters() {
    return this.embedsMany('App/Models/Filter')
  }

  contacts() {
    return this.referMany('App/Models/Contact')
  }
}

My Controller:

/**
   * Store
   *
   * @param {any} request
   * @param {any} response
   * @returns
   *
   * @memberOf EmailContentController
   *
   */
  async send({
    request,
    response,
    instance,
    params,
    auth
  }) {
    const user = await auth.getUser()
    var embedInstance = await instance.emailContents()
      .find(params.embedId)
    if (!embedInstance) {
      throw ResourceNotFoundException.invoke(`Can not find model with id "${params.emailId}"`)
    }
    /* We find our email properties */
    const properties = await user.properties().where({
      is_email: true
    }).fetch()
    const emailDbFields = []
    for (let i = 0; i < properties.length; i++) {
      emailDbFields.push(properties.db_name)
    }

    const segmentationRefs = request.input('segmentations', [])
    const emailList = [];
    for (let i = 0; i < segmentationRefs.length; i++) {
      const segmentationRef = segmentationRefs[i];
      const segmentation = (await user.segmentations().find(segmentationRef))
      const contacts = await segmentation.contacts().fetch()
      for (let j = 0; j < contacts.length; j++) {
        const contact = contacts[j];
        for (const key in contact) {
          if (contact.hasOwnProperty(key)) {
            if (key in emailDbFields) {
              emailList.push(contact[key])
            }
          }
        }
      }
    }

    const segmentations = (await user.segmentations().where({
      "_id": {
        "in": segmentationRefs
      }
    }).fetch()).rows
    return response.apiUpdated(segmentations)
  }

It gives me the following error:

{
    "status": 500,
    "message": "segmentation.contacts is not a function",
    "traces": "TypeError: segmentation.contacts is not a function\n    at EmailContentController.send (/home/francisco/Repositories/Nuviio/Mercurio/server-v2/app/Controllers/Http/Api/EmailContentController.js:134:43)\n    at <anonymous>"
}

If i change the find line for the following code:

const segmentation = (await user.segmentations()
        .where({
          _id: segmentationRef
        })
        .fetch()).rows[0]

It works and does not give that error.

franciscosucre avatar Jan 22 '18 01:01 franciscosucre

@franciscosucre you can try first() method

const segmentation = await user.segmentations().where({ _id: segmentationRef }).first()

duyluonglc avatar Jan 22 '18 18:01 duyluonglc

The code works! but it is still weird that it does not work when using find(), are internally this methods different? By the way is there a way to make this query:

/* We find our email properties */
const properties = (await user.properties().where({is_email: true}).fetch()).rows

Without it returning a serializer with the row attribute? I mean i would like to get the data directly like method you just gave me.

franciscosucre avatar Jan 22 '18 23:01 franciscosucre