robfallows / tunguska-reactive-aggregate

Reworks jcbernack:reactive-aggregate for ES6/ES7 and Promises
MIT License
51 stars 27 forks source link

Cannot read property 'dataByKey' of undefined #74

Closed JanMP closed 1 year ago

JanMP commented 1 year ago

The following aggregation with a $lookup phase throws an error on v1.3.10 (1.3.6 works fine) when changing data in one of the feedback documents (initial load works fine):

import {Meteor} from 'meteor/meteor'
import {Mongo} from 'meteor/mongo'
import SimpleSchema from 'simpl-schema'
import {ValidatedMethod} from 'meteor/mdg:validated-method'
import {ReactiveAggregate} from 'meteor/tunguska:reactive-aggregate'
import {createTableDataAPI, currentUserMustBeInRole} from 'meteor/janmp:sdui'
import {createOperation, embedding, search} from 'meteor/janmp:chatterbrain'
import {Feedback} from './Feedback'
import _ from 'lodash'

SimpleSchema.extendOptions ['sdTable', 'uniforms']

export Content = new Mongo.Collection 'content'

schemaDefinition =
  projectId:
    type: String
    label: 'Projekt ID'
    optional: true
  referenceId:
    type: String
    label: 'Referenz ID'
    optional: true
  title:
    type: String
    label: 'Titel'
    optional: true
  text:
    type: String
    label: 'Text'
    optional: true
  url:
    type: String
    label: 'URL'
    optional: true

sourceSchema = new SimpleSchema schemaDefinition

export dataOptions = createTableDataAPI
  sourceName: 'content'
  sourceSchema: sourceSchema
  collection: Content
  viewTableRole: 'admin'
  showRowCount: true
  canEdit: true

# Additional Publications:
embed = createOperation?(endpoint: embedding) ? -> run: -> console.log 'no embedding endpoint'

export ContentForQueryString = if Meteor.isClient then new Mongo.Collection 'content.forQueryString'

if Meteor.isServer

  Meteor.publish 'content.forQueryString', ({queryString, projectId, limit = 10}) ->
    pub = this

    unless queryString? and typeof queryString is 'string' and queryString.length > 3
      pub.ready()
      return

    unless projectId? and typeof projectId is 'string'
      pub.ready()
      return

    vector = await embed.run queryString
    response = await search {collectionName: 'bonedo_test', vector, limit}

    referenceIdsFromResponse = response.result.map ({id}) -> "#{id}"

    pipeline = [
      $match:
        projectId: projectId
        referenceId:
          $in: referenceIdsFromResponse
    ,
      $addFields:
        scoresForIds: response.result.map ({id, score}) -> {referenceId: id, score}
    ,
      $addFields:
        knnScore:
          $arrayElemAt: ['$scoresForIds.score', $indexOfArray: ['$scoresForIds.referenceId', '$referenceId']]
    ,
      $unset: 'scoresForIds'
    ,
      $lookup:
        from: 'feedback'
        localField: '_id'
        foreignField: 'queryContentId'
        as: 'similarContentKnnFeedback'
    ,
      $unwind: '$similarContentKnnFeedback'
    ,
      $addFields:
        'similarContentKnnFeedback.userThumbsUp':
          $cond:
            if: $isArray: '$similarContentKnnFeedback.thumbsUp'
            then: $in: [pub.userId, '$similarContentKnnFeedback.thumbsUp']
            else: false
        'similarContentKnnFeedback.userThumbsDown':
          $cond:
            if: $isArray: '$similarContentKnnFeedback.thumbsDown'
            then: $in: [pub.userId, '$similarContentKnnFeedback.thumbsDown']
            else: false
    ,
      $addFields:
        'similarContentKnnFeedback.userThumbs':
          $cond:
            if: '$similarContentKnnFeedback.userThumbsUp'
            then: 'up'
            else:
              $cond:
                if: '$similarContentKnnFeedback.userThumbsDown'
                then: 'down'
                else: null
    ,
      $unset: [
        'similarContentKnnFeedback.userThumbsUp'
        'similarContentKnnFeedback.userThumbsDown'
        'similarContentKnnFeedback.thumbsUp'
        'similarContentKnnFeedback.thumbsDown'
      ]
    ,
    #get content for contentIds in similarContentKnnFeedback
    $lookup:
      from: 'content'
      localField: 'similarContentKnnFeedback.contentId'
      foreignField: '_id'
      as: 'similarContentKnnFeedback.contentArray'
    ,
      $addFields:
        'similarContentKnnFeedback.content':
          $arrayElemAt: ['$similarContentKnnFeedback.contentArray', 0]
    ,
      $unset: 'similarContentKnnFeedback.contentArray'
    ,
      $addFields:
        'similarContentKnnFeedback.feedbackId': '$similarContentKnnFeedback._id'
        'similarContentKnnFeedback.text': '$similarContentKnnFeedback.content.text'
        'similarContentKnnFeedback.title': '$similarContentKnnFeedback.content.title'
        'similarContentKnnFeedback.url': '$similarContentKnnFeedback.content.url'
    ,
      $unset: [
        'similarContentKnnFeedback.content'
        'similarContentKnnFeedback._id'
        'similarContentKnnFeedback.referenceId'
        'similarContentKnnFeedback.queryContentId'
      ]
    ,
      $sort:
        'similarContentKnnFeedback.knnScore': -1
    ,
      $group:
        _id: '$_id'
        doc: $first: '$$ROOT'
        similarContentKnnFeedback: $push: '$similarContentKnnFeedback'
    ,
      $addFields:
        'doc.similarContentKnnFeedback': '$similarContentKnnFeedback'
    ,
      $replaceRoot:
        newRoot: '$doc'
    ]

    options =
      clientCollection: 'content.forQueryString'
      noAutomaticObserver: true
      observers: [
        Content.find referenceId: $in: referenceIdsFromResponse
        Feedback.find referenceId: $in: referenceIdsFromResponse
      ]

    ReactiveAggregate this, Content, pipeline, options

The Error:

Exception in changedobserveChanges callback: errorClass [Error]: Cannot read property 'dataByKey' of undefined
    at update (packages/tunguska:reactive-aggregate/aggregate.js:282:13)
    at debounce (packages/tunguska:reactive-aggregate/aggregate.js:301:7)
    at changed (packages/tunguska:reactive-aggregate/aggregate.js:323:9)
    at runWithEnvironment (packages/meteor.js:1486:24)
    at packages/meteor.js:1499:14
    at packages/mongo/observe_multiplex.js:178:30
    at Array.forEach (<anonymous>)
    at Function._.each._.forEach (packages/underscore.js:139:11)
    at Object.task (packages/mongo/observe_multiplex.js:172:9)
    at Meteor._SynchronousQueue.SQp._run (packages/meteor.js:1026:16)
    at packages/meteor.js:1003:12 {
  path: '',
  sanitizedError: errorClass [Error]: tunguska:reactive-aggregate [Error]
      at errorClass.<anonymous> (packages/tunguska:reactive-aggregate/aggregate.js:11:27)
      at new errorClass (packages/meteor.js:718:17)
      at update (packages/tunguska:reactive-aggregate/aggregate.js:282:13)
      at debounce (packages/tunguska:reactive-aggregate/aggregate.js:301:7)
      at changed (packages/tunguska:reactive-aggregate/aggregate.js:323:9)
      at runWithEnvironment (packages/meteor.js:1486:24)
      at packages/meteor.js:1499:14
      at packages/mongo/observe_multiplex.js:178:30
      at Array.forEach (<anonymous>)
      at Function._.each._.forEach (packages/underscore.js:139:11)
      at Object.task (packages/mongo/observe_multiplex.js:172:9)
      at Meteor._SynchronousQueue.SQp._run (packages/meteor.js:1026:16)
      at packages/meteor.js:1003:12 {
    isClientSafe: true,
    error: 'Error',
    reason: 'tunguska:reactive-aggregate',
    details: undefined,
    errorType: 'Meteor.Error'
  },
  errorType: 'tunguska:reactive-aggregate'
}
robfallows commented 1 year ago

Thanks for the report. Can you let me know if this issue also affects 1.3.7, 1.3.8 and/or 1.3.9?

JanMP commented 1 year ago

1.3.7 and 1.3.10 initial load fine, above error on change in lookup 1.3.8 and 1.3.9 initial load fails with a different error (also on other pipelines without lookups that don't have the dataByKey problem) see below:

Exception from sub content.forQueryString id bdmZEDZ7Jf79AceJa TypeError: Cannot convert undefined or null to object
    at Function.entries (<anonymous>)
    at ReactiveAggregate (packages/tunguska:reactive-aggregate/aggregate.js:56:37)
    at imports/api/Content.coffee:173:5
    at /Users/jan-michaelpilgenroeder/.meteor/packages/promise/.0.12.2.15o915w.zdms++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/fiber_pool.js:43:40
 => awaited here:
    at Function.Promise.await (/Users/jan-michaelpilgenroeder/.meteor/packages/promise/.0.12.2.15o915w.zdms++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/meteor-promise/promise_server.js:56:12)
    at packages/meteor.js:367:22
    at Meteor.EnvironmentVariable.EVp.withValue (packages/meteor.js:1389:31)
    at Subscription._runHandler (packages/ddp-server/livedata_server.js:1123:60)
    at Session._startSubscription (packages/ddp-server/livedata_server.js:934:9)
    at Session.sub (packages/ddp-server/livedata_server.js:673:12)
    at packages/ddp-server/livedata_server.js:603:43
robfallows commented 1 year ago

What version of Meteor are you using?

JanMP commented 1 year ago

2.12

robfallows commented 1 year ago

Would you be able to retest with the new branch: bugfix/object-chaining please?

JanMP commented 1 year ago

still get the dataByKey Error

robfallows commented 1 year ago

I have bumped the package version in the new branch in case meteor's failing to see the change, but can you also please confirm you followed this process to test the branch:

  1. Switch to your project root: cd /path/to/your/project
  2. Ensure a packages directory exists: mkdir -p packages
  3. Switch to packages directory: cd packages
  4. Clone this repo: git clone git@github.com:robfallows/tunguska-reactive-aggregate.git
  5. Switch to clone directory: cd tunguska-reactive-aggregate
  6. Checkout branch: git checkout bugfix/object-chaining
  7. Switch back to your project directory: cd ../..
  8. Retest your project.

Note: you will need to git pull if these were the steps you followed, in order to get the new version number.

Thanks.

JanMP commented 1 year ago

you are right, had not checked out the correct branch...

now I get this error on changing feedback:

Exception in changedobserveChanges callback: errorClass [Error]: _sub$_session$collect2.keys is not iterable (cannot read property Symbol(Symbol.iterator))
    at update (packages/tunguska:reactive-aggregate/aggregate.js:282:13)
    at debounce (packages/tunguska:reactive-aggregate/aggregate.js:301:7)
    at changed (packages/tunguska:reactive-aggregate/aggregate.js:323:9)
    at runWithEnvironment (packages/meteor.js:1486:24)
    at packages/meteor.js:1499:14
    at packages/mongo/observe_multiplex.js:178:30
    at Array.forEach (<anonymous>)
    at Function._.each._.forEach (packages/underscore.js:139:11)
    at Object.task (packages/mongo/observe_multiplex.js:172:9)
    at Meteor._SynchronousQueue.SQp._run (packages/meteor.js:1026:16)
    at packages/meteor.js:1003:12 {
  path: '',
  sanitizedError: errorClass [Error]: tunguska:reactive-aggregate [Error]
      at errorClass.<anonymous> (packages/tunguska:reactive-aggregate/aggregate.js:11:27)
      at new errorClass (packages/meteor.js:718:17)
      at update (packages/tunguska:reactive-aggregate/aggregate.js:282:13)
      at debounce (packages/tunguska:reactive-aggregate/aggregate.js:301:7)
      at changed (packages/tunguska:reactive-aggregate/aggregate.js:323:9)
      at runWithEnvironment (packages/meteor.js:1486:24)
      at packages/meteor.js:1499:14
      at packages/mongo/observe_multiplex.js:178:30
      at Array.forEach (<anonymous>)
      at Function._.each._.forEach (packages/underscore.js:139:11)
      at Object.task (packages/mongo/observe_multiplex.js:172:9)
      at Meteor._SynchronousQueue.SQp._run (packages/meteor.js:1026:16)
      at packages/meteor.js:1003:12 {
    isClientSafe: true,
    error: 'Error',
    reason: 'tunguska:reactive-aggregate',
    details: undefined,
    errorType: 'Meteor.Error'
  },
  errorType: 'tunguska:reactive-aggregate'
}
robfallows commented 1 year ago

I've made a couple of tweaks to the property chaining. Please pull the updates and retest.

JanMP commented 1 year ago

It's working 🎉

robfallows commented 1 year ago

Awesome! I'll issue a new release.