stalniy/ucast

[mongo2js] Question: will querying primitive values with top level operators be supported?

J3m5 opened this issue ยท 13 comments

J3m5 commented

Basic example:

const query = filter({ $lt: 3,  $gt: 0  });

const data = 2

const result = query(data)
// true
// now return  Unknown top level operator "$lt"

I was unsure whether it make sense in general. Never used sift this way, also casl doesn't have such need. That's why it was not fully implemented.

By the way, it can be emulated for arrays with $elemMatch:

const query = filter({ 
  values: { elemMatch: { $lt: 3,  $gt: 0  } } 
})
const values = [1, 2, 3, 4];
const result = query({ values });

Do you have a good case where such behavior is desirable?

J3m5 commented

Well, anywhere I check values or types against multiple conditions or when using it as a predicate of another function.

const filteredValues = [1, 2, 3, 4].filter(filter({ $lt: 3, $gt: 1 }));

is more readable, simpler and more familiar than

const filteredValues = [1, 2, 3, 4].filter((values) =>
  filter({ values: { elemMatch: { $lt: 3, $gt: 1 } } })({ values })
);

It can also be useful in simple if statements when you have to check multiple conditions, or when you use utility functions like lodash flow or ramda pipe.

if (score > 1 && score < 3) {
  callFunc(score);
}

if (filter({ $gt: 1, $lt: 3 })(score)) {
  callFunc(score);
}
// or after refactoring
const isBadScore = filter({ $gt: 1, $lt: 3 });
if (isBadScore(score) {
  callFunc(score);
}

It help you refactoring conditions when then become more complex without having to manually create functions etc.
And those are simple conditions and values, you can use this pattern with arrays of numbers and strings, with mixed types and more complex conditions.

if I provide a separate function primitiveFilter (or valueFilter), will this make you happy? :)

const isBadScore = primitiveFilter({ $gt: 1, $lt: 3 });
if (isBadScore(score) {
  callFunc(score);
}
J3m5 commented

This would be nice, yes :)
And it would better demonstrate the intent, but maybe with a shorter name ^^.

It leads me to make another request :)
I'm not sure if the name "filter" is the best to define what mongo2js do, and it might bring confusion as there is already a method of the Array object.

IMO this discussion could have it's own issue, what do you think ?

Cool :) It's fine to discuss it in this issue. Any suggestions are very welcome

J3m5 commented

Here is a quick list (in order of preference)

scan
probe
audit
gauge
conform
comply
control
pattern
comb
check
inspect

I've been looking for a word related to castles to stay in the theme but I didn't find anything...

None of that looks better than filter for me :) Maybe the best way is to use mongo2js name or just mongo. Anyway you can alias it as you want.

So, I suggest:

  1. mongo for objects and mongoField for primitives
  2. query for objects and fieldQuery for primitives

What do you like the most?

by the way, ucast is standalone library which has nothing to do with casl (in the end), so we can use whatever names we want.

PS: in terms of casl, a good name would be guard :)

J3m5 commented

guard is nice!
I find query a bit too generic and it's already used in feathers as the query object and probably in a lot of other frameworks.
For mongo, I'm not sure taking the name as it stands is a good idea, but we could find something like Mingo by changing one or 2 letters.
For the import name, the solution would be to export it as a default export, in that case, no need to rename it, you import it with the name you want.

So, then let it be guard and squire for field))

J3m5 commented

Those names are cool, it's ok for me.

J3m5 commented

Great! Thanks!

Available from @ucast/mongo2js@1.2.0