senecajs / seneca-mongo-store

Node.js Seneca data storage plugin for MongoDB
MIT License
35 stars 42 forks source link

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

Open jeromevalentin opened 3 years ago

jeromevalentin commented 3 years ago

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]
            }
          }
        }
      }
    }
rjrodger commented 3 years ago

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

lilsweetcaligula commented 3 years ago

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

rjrodger commented 3 years ago

let's resolve this before next release

lilsweetcaligula commented 3 years ago

@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?

jeromevalentin commented 3 years ago

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.

rjrodger commented 3 years ago

@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