Skip to content

Commit 164bf45

Browse files
committed
feat: query() function to handle queries similar to mongodb
1 parent 9246c5d commit 164bf45

File tree

1 file changed

+146
-2
lines changed

1 file changed

+146
-2
lines changed

src/index.js

+146-2
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,12 @@
154154
for (let i = 0; i < subpath.length; i++) {
155155
jsonData = jsonData[subpath[i]];
156156
if (!jsonData)
157-
return jsonData;
157+
return;
158158
}
159+
159160
return jsonData;
160161
} catch (error) {
161162
console.log("Error in getValueFromObject", error);
162-
return;
163163
}
164164
}
165165

@@ -560,6 +560,149 @@
560560
return queryResult;
561561
}
562562

563+
function query(data, query) {
564+
if (query.$and) {
565+
for (let i = 0; i < query.$and.length; i++) {
566+
if (!query(data, query.$and[i]))
567+
return false
568+
}
569+
}
570+
571+
if (query.$nor) {
572+
for (let i = 0; i < query.$nor.length; i++) {
573+
if (query(data, query.$nor[i]))
574+
return false;
575+
}
576+
}
577+
578+
for (let key of Object.keys(query)) {
579+
if (key === '$and' || key === '$or')
580+
continue
581+
if (!isMatch(data, { [key]: query[key] }))
582+
return false
583+
}
584+
585+
if (query.$or) {
586+
for (let i = 0; i < query.$or.length; i++) {
587+
if (query(data, query.$or[i]))
588+
return true
589+
}
590+
}
591+
592+
return true;
593+
}
594+
595+
function isMatch(data, query) {
596+
for (let key of Object.keys(query)) {
597+
let dataValue = getValueFromObject(data, key)
598+
if (!dataValue)
599+
return false
600+
601+
if (typeof query[key] === 'string' || typeof query[key] === 'number' || typeof query[key] === 'boolean') {
602+
if (Array.isArray(dataValue))
603+
return dataValue.includes(query[key])
604+
else
605+
return dataValue === query[key]
606+
} else if (Array.isArray(query[key])) {
607+
if (Array.isArray(dataValue)) {
608+
return isEqualArray(dataValue, query[key]);
609+
} else {
610+
return false;
611+
}
612+
} else {
613+
for (let property of Object.keys(query[key])) {
614+
if (!property.startsWith('$')) {
615+
if (typeof dataValue !== 'object') {
616+
return false;
617+
} else
618+
return isMatch({ [property]: getValueFromObject(dataValue, property) }, { [property]: query[key][property] })
619+
} else {
620+
let queryValue = query[key][property]
621+
let queryStatus = false
622+
switch (property) {
623+
case '$eq':
624+
if (Array.isArray(dataValue) && Array.isArray(queryValue)) {
625+
queryStatus = isEqualArray(dataValue, queryValue);
626+
} else {
627+
queryStatus = (dataValue === queryValue);
628+
}
629+
break;
630+
case '$ne':
631+
if (Array.isArray(dataValue) && Array.isArray(queryValue)) {
632+
queryStatus = !isEqualArray(dataValue, queryValue);
633+
} else {
634+
queryStatus = (dataValue !== queryValue);
635+
}
636+
break;
637+
case '$not':
638+
queryStatus = !isMatch(data, { [key]: query[key]['$not'] });
639+
break;
640+
case '$lt':
641+
queryStatus = (dataValue < queryValue)
642+
break;
643+
case '$lte':
644+
queryStatus = (dataValue <= queryValue)
645+
break;
646+
case '$gt':
647+
queryStatus = (dataValue > queryValue)
648+
break;
649+
case '$gte':
650+
queryStatus = (dataValue >= queryValue)
651+
break;
652+
case '$in':
653+
if (Array.isArray(dataValue)) {
654+
queryStatus = dataValue.some(element => queryValue.includes(element));
655+
} else {
656+
queryStatus = queryValue.includes(dataValue);
657+
}
658+
break;
659+
case '$nin':
660+
if (Array.isArray(dataValue)) {
661+
queryStatus = !dataValue.some(element => queryValue.includes(element));
662+
} else {
663+
queryStatus = !queryValue.includes(dataValue);
664+
}
665+
break;
666+
case '$all':
667+
if (Array.isArray(dataValue) && Array.isArray(queryValue)) {
668+
queryStatus = queryValue.every(element => dataValue.includes(element));
669+
}
670+
break;
671+
case '$elemMatch':
672+
if (Array.isArray(data[key])) {
673+
queryStatus = data[key].some(element => isMatch(element, query[key][property]));
674+
}
675+
break;
676+
case '$size':
677+
if (Array.isArray(dataValue)) {
678+
queryStatus = (dataValue.length === queryValue);
679+
}
680+
break;
681+
case '$exists':
682+
queryStatus = (queryValue ? data.hasOwnProperty(key) : !data.hasOwnProperty(key));
683+
break;
684+
case '$regex':
685+
if (typeof dataValue === 'string') {
686+
let regex = new RegExp(queryValue);
687+
queryStatus = regex.test(dataValue);
688+
}
689+
break;
690+
default:
691+
console.log('unknown operator')
692+
break;
693+
694+
}
695+
if (!queryStatus)
696+
return false
697+
698+
}
699+
}
700+
return true
701+
}
702+
703+
}
704+
}
705+
563706
function isEqualArray(arr1, arr2) {
564707
if (arr1.length !== arr2.length) {
565708
return false;
@@ -755,6 +898,7 @@
755898
cssPath,
756899
queryElements,
757900
checkMediaQueries,
901+
query,
758902
queryData,
759903
searchData,
760904
sortData,

0 commit comments

Comments
 (0)