先说总结:合理运用mongo的操作符可以实现各类的查询!mongo操作符文档
我有一个商品集合,它包含以下的文档,我需要对他进行分页、排序的查询
{
"nameCn" : "商品1",
"prices" : [
{
"_id" : ObjectId("625ad3faac803944c8d7a6d0"),
"currency" : "SGD",
"value" : 10
},
{
"_id" : ObjectId("625ad3faac803944c8d7a6d1"),
"currency" : "MYR",
"value" : 20
}
],
},
{
"nameCn" : "商品2",
"prices" : [
{
"_id" : ObjectId("625ad3faac803944c8d7a6e4"),
"currency" : "SGD",
"value" : 12
},
{
"_id" : ObjectId("625ad3faac803944c8d7a6e5"),
"currency" : "MYR",
"value" : 22
}
],
}
...
在ui界面会根据用户自身的币种属性显示不同的价格,现在需要根据prices和currency对其进行排序。通过在查询结果中添加一个自定义值realPrice,再由realPrice进行排序即可
{
$addFields: {
realPrice: {
$let: {
vars: {
price_1: {
$arrayElemAt: [
{
$filter: {
input: '$prices',
cond: { $eq: ['$$this.currency', user.currency] },
},
},
0,
],
},
},
in: '$$price_1.value',
},
},
},
},
{ $sort: {'realPrice':-1}},
}
这样用户就能看到根据其币种来排序的商品了,但这还没完。我还由一个议价集合,不同的用户对某一些商品存在一个特殊价格。它有这些文档
{
"currency" : "SGD",
"price" : 230,
"user" : ObjectId("625d31774525bc4c21c6ac89"),
"good" : ObjectId("6260d5507e8392e6b44ef235"),
},
{
"currency" : "SGD",
"price" : 330,
"user" : ObjectId("625d31774525bc4c21c6ac89"),
"good" : ObjectId("625ad3faac803944c8d7a729"),
}
...
此时我的商品列表的查询变得相当复杂,在查询用户看到的商品价格列表时,需要先匹配到议价表中对应的用户商品价格,通过操作符pipeline来对需要lookup的集合匹配多个条件。
再添加realPrice字段进行排序,当商品存在该用户的议价时则显示议价价格,不存在则显示公用价格,此时的排序需求就变的更加复杂了,实现结果如下
{
$lookup: {
from: 'pricebargain',
let: {
good: '$_id',
},
pipeline: [
{
$match: {
$expr: {
$and: [
{
$eq: ['$good', '$$good'],
},
],
},
user: ObjectID(user._id),
},
},
],
as: 'priceBargainInfo',
},
},
{
$unwind: {
path: '$priceBargainInfo',
preserveNullAndEmptyArrays: true,
},
},
{
$addFields: {
realPrice: {
$let: {
vars: {
price_1: '$priceBargainInfo.price',
price_2: {
$arrayElemAt: [
{
$filter: {
input: '$prices',
cond: { $eq: ['$$this.currency', user.currency] },
},
},
0,
],
},
},
in: { $cond: ['$$price_1', '$$price_1', '$$price_2.value'] },
},
},
},
}
先得到用户的议价信息,注入到price_1中,在匹配商品对应用户币种的价格,注入到price_2中,最终通过mongo提供的$cond三目运算符,来决定最终应用的价格。这样就能实现我们的排序效果了。
mongo还有很多好用的操作符,养成学习阅读官方文档的习惯,遇到新的需求就能快速解决啦~