📜  mongoose $in 运算符顺序不被尊重 - Javascript (1)

📅  最后修改于: 2023-12-03 15:17:42.579000             🧑  作者: Mango

Mongoose $in 运算符顺序不被尊重

在使用 mongoose 中的 $in 运算符时,我们可能会遇到顺序不被尊重的问题,即查询结果的顺序与传递的数组顺序不一致。本文将介绍这个问题的原因和解决办法。

问题说明

假设我们有一个名为 users 的集合,包含以下文档:

[
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 35 },
  { name: 'Dave', age: 40 },
  { name: 'Eva', age: 45 }
]

现在我们想查询年龄为 40 和 25 的用户,代码如下:

const ages = [40, 25];
const result = await User.find({ age: { $in: ages } });

期望的结果是先返回年龄为 40 的用户,再返回年龄为 25 的用户,即

[
  { name: 'Dave', age: 40 },
  { name: 'Alice', age: 25 }
]

然而实际上,可能会得到以下结果:

[
  { name: 'Alice', age: 25 },
  { name: 'Dave', age: 40 }
]
原因分析

以上结果的原因是 mongodb 查询语句返回的结果是按照文档在磁盘上的存储顺序返回的。由于文档在磁盘上的存储顺序是由 mongodb 自动管理的,因此无法保证查询结果的顺序与传递的数组顺序一致。

解决办法

解决这个问题有两种办法:

1. 手动排序

手动排序是最简单的解决办法。我们可以在查询结果返回后,使用 JavaScript 的 Array.sort 方法按照传递的数组顺序进行排序,代码如下:

const ages = [40, 25];
const result = await User.find({ age: { $in: ages } });
const sortedResult = result.sort((a, b) => ages.indexOf(a.age) - ages.indexOf(b.age));

这样我们就得到了期望的结果:

[
  { name: 'Dave', age: 40 },
  { name: 'Alice', age: 25 }
]
2. 使用 $or 运算符

另一种解决办法是使用 $or 运算符,代码如下:

const ages = [40, 25];
const orConditions = ages.map(age => ({ age }));
const result = await User.find({ $or: orConditions });

这个方法的原理是将传递的数组转换为一组 $or 条件,查询时使用 $or 运算符进行查询。这样查询结果的顺序就是传递的数组顺序。

结论

在使用 mongoose 的 $in 运算符时,我们需要注意查询结果的顺序可能与传递的数组顺序不一致。为了得到期望的查询结果,我们可以手动排序或者使用 $or 运算符。