如何实现一个 ORM 类似的 find 链式调用
更多描述 如下代码所示,使用
find
函数实现链式调用
const data = [
{userId: 8, title: 'title1'},
{userId: 11, title: 'other'},
{userId: 15, title: null},
{userId: 19, title: 'title2'}
];
// 查找data中,符合where中条件的数据,并根据orderBy中的条件进行排序
const result = find(data).where({
"title": /\d$/ // 这里意思是过滤出数组中,满足title字段中符合 /\d$/的项
}).orderBy('userId', 'desc'); // 这里的意思是对数组中的项按照userId进行倒序排列
//=> 返回 [{ userId: 19, title: 'title2'}, { userId: 8, title: 'title1' }];
console.log(result.value);
> Issue
欢迎在 Gtihub Issue 中回答此问题: [Issue 712](https://github.com/shfshanyue/Daily-Question/issues/712)
> Author
回答者: [shfshanyue](https://github.com/shfshanyue)
代码见 codepen,[如何实现链式调用](https://codepen.io/shanyue/pen/abWQLZv?editors=0012)
``` js
function find (data) {
return {
data,
where (match) {
this.data = this.data.filter((item) => {
return Object.entries(match).every(([key, value]) => {
if (value instanceof RegExp) {
return value.test(item[key])
}
return item[key] === value
})
})
return this
},
orderBy (key, type) {
this.data.sort((x, y) => type !== 'desc' ? x[key] - y[key] : y[key] - x[key])
return this
}
}
}
Author 回答者: haotie1990
function find(data) {
class FindManager {
constructor(data) {
this.data = data;
}
where(query) {
const data = [...this.data];
return new FindManager(
data.filter((item) => {
return Object.entries(query).every(([key, filter]) => {
if (
Object.prototype.toString.call(filter).slice(8, -1) === "Regex"
) {
return filter.test(item[key]);
} else {
return filter === item[key];
}
});
}),
);
}
orderBy(key, order) {
const data = [...this.data];
data.sort((a, b) => {
return order === "asc" ? a[key] - b[key] : b[key] - a[key];
});
return new FindManager(data);
}
get value() {
return this.data;
}
}
return new FindManager(data);
}
Author 回答者: heretic-G
function find(data) {
const temp = Array.isArray(data) ? [...data] : { ...data };
let opt = {
where: function where(opt) {
return find(
Object.entries(opt).reduce((prev, [key, match]) => {
return prev.filter((curr) => {
return match.test(curr[key]);
});
}, this),
);
},
orderBy: function order(key, type) {
return this.sort((prev, next) => {
switch (type) {
case "desc":
return next - prev;
case "asc":
return prev - next;
default:
return prev - next;
}
});
},
};
Object.setPrototypeOf(opt, Array.prototype);
Object.setPrototypeOf(temp, opt);
return temp;
}
Author 回答者: vandvassily
// 综合一下两位大佬的写法
class Find {
constructor(data) {
this.data = [...data];
}
where(query) {
this.data = this.data.filter((item) => {
return Object.entries(query).every(([key, value]) => {
if (value instanceof RegExp) {
return value.test(item[key]);
} else {
return item[key] === value;
}
});
});
return this;
}
orderBy(key, type) {
this.data = this.data.sort((a, b) =>
type !== "desc" ? a[key] - b[key] : b[key] - a[key],
);
return this;
}
get value() {
return this.data;
}
}
function find(data) {
return new Find(data);
}