In StrongLoop, the "in" filter it is not working for fields of string type. I'm posting here to see if anyone else have seen this issue or if its a known issue in StrongLoop MongoDB connector. Also to see if there is any workaround.
It does work for me for integer types fields. But when I test it on string type it doesnt return anything.
I tried the same queries directly in my database MongoDB command line and both integer and string filters worked. So I know my format is correct and that the query I'm trying is valid.
This is part of the code that I'm using in my StrongLoop model custom API to query the database using the in filter.
This works fine:
Grades.find({where: {grade: {in:[1,2]} }},
This doest not work:
Grades.find({where: {subject: {in:["math","biology"]} }},
I didn't put much code here since this requires both database setup and strongloop setup, let me know and I can add more code if necessary.
Thanks, Carlos
The issue seem to be outside the mongo-db connector. After debugging the following connector (loopback-connector-mongodb/lib/mongodb.js) I see the "function all" is receiving the incorrect filter when the field type is string.
loopback-connector-mongodb/lib/mongodb.js:
//
// Find matching model instances by the filter
//
// param {String} model The model name
// param {Object} filter The filter
// param {Function} [callback] The callback function
//
MongoDB.prototype.all = function all(model, filter, options, callback) {
var self = this;
if (self.debug) {
debug('all', model, filter);
}
console.log("carlos999: HERE!!!!");
if(filter.where['subject']){
console.log('carlos998: cond:%s cond.constructor.name:%s', filter.where['subject'], filter.where['subject'].constructor.name);
}
if(filter.where['grade']){
console.log('carlos997: cond:%s cond.constructor.name:%s', filter.where['grade'], filter.where['grade'].constructor.name);
}
My model:
"grade": {
"type": "number",
"required": true
},
"subject": {
"type": "string",
"required": true
},
In below sample code you can see how the Array is process properly when the field type is Integer (in this case for debugging purpose, I passed string values inside the array, you can see how they propagate all the way to the MongoDB call). But in the case of string type field ("subject"). The array is not processed properly.
This case works okay
Query:
Grades.find({where: {grade: {in:["math","biology"]} }},
Output:
carlos997: cond:[object Object] cond.constructor.name:Object
carlos929: cond:[object Object] cond.constructor.name:Object
carlos29: k:grade cond:[object Object] cond.constructor.name:Object cond.options:undefined
carlos: propName:grade prop:[object Object]
carlos: spec: in k:grade cond:math,biology cond.constructor.name:Array cond.options:undefined
carlos: MongoDB: model=grades command=find [ { importance: { '$in': [Object] } }, [Function] ]
This case has an issue (possible StrongLoop bug):
Query:
Grades.find({where: {subject: {in:["math","biology"]} }},
Output:
carlos998: cond:[object Object] cond.constructor.name:String
carlos929: cond:[object Object] cond.constructor.name:String
carlos29: k:subject cond:[object Object] cond.constructor.name:String cond.options:undefined
carlos: propName:subject prop:[object Object]
carlos: spec: false k:subject cond:[object Object] cond.constructor.name:String cond.options:undefined
carlos: MongoDB: model=grades command=find [ { subject: '[object Object]' }, [Function] ]
I'm continuing debug, but would be great if other people joins the effort.
Thanks, Carlos
To confirm the problem is related to the String type. I changed my model to use "number" instead of "string" just to confirm that the array used by the $in filter is handled properly. And indeed, it worked.
Model change:
"grade": {
"type": "number", //changed from string
"required": true
},
"subject": {
"type": "number",
"required": true
},
Output:
carlos998: cond:[object Object] cond.constructor.name:Object
carlos929: cond:[object Object] cond.constructor.name:Object
carlos29: k:subject cond:[object Object] cond.constructor.name:Object cond.options:undefined
carlos: propName:subject prop:[object Object]
carlos: spec: in k:subject cond:math,biology cond.constructor.name:Array cond.options:undefined
carlos: MongoDB: model=grades command=find [ { subject: { '$in': [Object] } }, [Function] ]
I think your operator name "in" is misspelled, and shuold be "inq".
The inq operator checks whether the value of the specified property matches any of the values provided in an array. The general syntax is:
{ where: { property: { inq: [val1, val2, ...] } } }
where: property is the name of a property (field) in the model being queried. val1, val2, and so on, are literal values in an array.