Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【Q691】如何实现一个 ORM 类似的 find 链式调用 #712

Open
shfshanyue opened this issue Aug 8, 2021 · 4 comments
Open

【Q691】如何实现一个 ORM 类似的 find 链式调用 #712

shfshanyue opened this issue Aug 8, 2021 · 4 comments
Labels

Comments

@shfshanyue
Copy link
Owner

如下代码所示,使用 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); 
@shfshanyue shfshanyue added the code label Aug 8, 2021
@shfshanyue
Copy link
Owner Author

shfshanyue commented Aug 8, 2021

代码见 codepen,如何实现链式调用

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
    }
  }
}

@haotie1990
Copy link

haotie1990 commented Aug 8, 2021

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);
}

@heretic-G
Copy link

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
}

@vandvassily
Copy link

// 综合一下两位大佬的写法
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);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants