node mongoose 查找 find ,当前端没有传过来筛选参数的时候 ,查找条件这块应该怎么写?

2021-09-19 20:41:04 +08:00
 PeakFish

上代码,下面的 id 字段 和 status 字段,如果前端没有传过来这个字段,那就 去掉筛选 或 者查询全部。这块应该怎么写?

const findList = await userModel
  // mongoose 的查找方法
  .find({
    nickname: { $regex: nicknameReg },
    _id: id ? ObjectId(id) : '查询字段的所有状态 或者 不查询这个字段, 这块需要怎么写?',
    status: status ? status : '查询字段的所有状态 或者 不查询这个字段, 这块需要怎么写?'
  })
5826 次点击
所在节点    Node.js
7 条回复
indo
2021-09-19 21:29:51 +08:00
我的想法应该是在函数入口加下判断,是否有入参,有责用入参,没有则空。
dream4ever
2021-09-19 23:45:05 +08:00
```js
const query = {
nickname: { $regex: nicknameReg }
}

if (id) {
query._id = ObjectId(id)
}
if (status) {
query.status = status
}

const findList = await userModel.find(query)
```
tukon479
2021-09-21 19:31:29 +08:00
用 $and 和 $or 就行了

`{ $and: [ { $or: [_id ? {_id}: {}] } , { $or: [ status ? {status} : {} ] } ] }`
ChangJingli
2021-11-09 11:03:32 +08:00
@dream4ever 目前 where 条件都是这么写的,条件多的时候感觉很不优雅
dream4ever
2021-11-09 21:03:36 +08:00
@ChangJingli 忽然想到其实可以把这个常用的需求封装成一个方法,做一层抽象,用起来就能“优雅”一点了
ChangJingli
2021-11-10 09:46:31 +08:00
@dream4ever 提取到 service 层仍是这样拼 where 条件;我尝试过封装公共 util 过滤条件,然而发现过滤条件跟业务有强耦合,util 不知道你什么时候需要保留空字符串,什么时候不需要,`null`类型 亦如此。
ouxch
2021-12-31 15:00:26 +08:00
最笨的办法当然就是写几个条件分支来组装最终的查询条件,例如:

```javascript
const filter = { nickname: { $regex: nicknameReg } }
if (!!id) fiter._id = ObjectId(id)
if (!!status) fiter.status = status
const findList = await userModel.find(filter)
```

---

其实这是一个如何让编码更加优雅的问题,不只适用于此处你这个问题,如果从事`JavaScript`开发,建议了解下函数式编程,这里以函数式编程库 [ramda]( https://ramda.cn/) 为例,看看写出来又是怎样的:

<br/>

首先定义一个通用的纯函数 `omitNil`

```javascript
const { reject, isNil } = require('ramda')
const omitNil = reject(isNil)
```

做个解释:

`isNil` 和 `reject` 都是 **ramda** 直接提供的函数,并且 **ramda** 的函数都是自动柯里化的;
`isNil` 的作用:检测输入值是否为 `null` 或 `undefined`;
`reject` 的作用:可视为 `filter` 的补操作,简言之 `filter` 是留下满足条件的元素、`reject` 是排除满足条件的元素;

将 `reject` 和 `isNil` 进行组合,得到 `omitNil` 函数,它的作用是:排除掉值为 `null` 或 `undefined` 的元素


做一个简单直观的测试,看看 `omitNil` 函数的作用:

```javascript
const obj = { a: 1, b: null, c: undefined }
omitNil(obj) // => { a: 1 }
obj // => { a: 1, b: null, c: undefined }

const arr = [1, null, undefined]
omitNil(arr) // => [ 1 ]
arr // => [1, null, undefined]
```

可以看到,`omitNil` 的返回值和输入参数相比,少了值为 `null` 或 `undefined` 的元素,并且没有修改原输入参数

<br/>

**现在回到楼主的问题**,就可以一行代码实现了:

```javascript
const findList = await userModel.find(omitNil({ nickname: { $regex: nicknameReg }, _id: id, status }))
```

<br/>

最后,**ramda** 的核心设计理念就包含了:数据不变性和函数无副作用,因此以上纯函数均不会改变输入参数的值。

<br/>

> 参考:
>
> https://ramda.cn
>
> https://ramdajs.com/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/802963

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX