seneca-mongo-store icon indicating copy to clipboard operation
seneca-mongo-store copied to clipboard

Listing entity with a query containing: $or mongo operator is no more possible

Open jeromevalentin opened this issue 4 years ago • 6 comments

Since the introduction of automatic conversion from array of values to a "$in" keyword... it is no more possible to perform query containing "$or" keyword.

As mongo is expecting an array value after such property, it is now failing as the real query sent converts the array to object with a "$in" property!

It misses the following test at the end of fixquery method:

        //delete q.id
      } else {
        for (var qp in q) {
          if ('id' !== qp && !qp.match(/\$$/)) {

// FIX START HERE
            // Preserving original mongo operators (like $or, $and, ...) which are expecting an array ....
            if (qp.startsWith('$')) {
              qq[qp] = q[qp]
            } else if (Array.isArray(q[qp])) {
// FIX STOP HERE
            
              qq[qp] = { $in: q[qp] }
            } else {
              qq[qp] = q[qp]
            }
          }
        }
      }
    }

jeromevalentin avatar Mar 19 '21 13:03 jeromevalentin

Thanks! @lilsweetcaligula can we develop test to validate this fix and apply it if so? Does it break anything else?

rjrodger avatar May 17 '21 11:05 rjrodger

@rjrodger Will look into it. Thank you for the report.

lilsweetcaligula avatar May 17 '21 15:05 lilsweetcaligula

let's resolve this before next release

rjrodger avatar Jun 04 '21 18:06 rjrodger

@jeromevalentin

Again, thank you for the report. You may pass the Mongo's native qualifiers via the native$ property in a query, like so:

const products = seneca.make('products')

products.list$({
  native$: {
    $or: [{ name: 'cherry' }, { price: 200 }]
  }
}, done)

Would that work for your use case?

lilsweetcaligula avatar Jun 06 '21 10:06 lilsweetcaligula

I knew that, but it implies to change a lot of existing queries in my app. That's why, I preferred to patch mongo-store like in my pull request, to remain compliant with previous version.Regards,JérômeLe 6 juin 2021 12:21, lilsweetcaligula @.***> a écrit : @jeromevalentin Again, thank you for report. You may pass the Mongo's native qualifiers via the native$ property in a query, like so: const products = seneca.make('products')

products.list$({ native$: { $or: [{ name: 'cherry' }, { price: 200 }] } }, done) Would it work for your use case?

—You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub, or unsubscribe.

jeromevalentin avatar Jun 06 '21 10:06 jeromevalentin

@jeromevalentin Try the pattern customization below - this should solve the problem for your use case:

seneca.add('role:entity,cmd:list', function mongo_custom(msg, reply) {
  let mongo_ops = Object.keys(msg).filter(prop=>prop.startsWith('$'))
  msg.native$ = mongo_ops.reduce((a,op)=>(a[op]=msg[op],a), {})
  return this.prior(msg, reply)
})

Use this after loading the mongo-store plugin Apologies, this code is not tested, but should give you the basic idea

rjrodger avatar Jun 18 '21 10:06 rjrodger