mongoose 操作符

本文详细介绍了MongoDB中的一些操作符,如$currentDate用于设置当前时间,$push用于数组操作,$expr和$setIsSubset配合使用进行复杂查询,$where用于实现复杂查询条件,以及$arrayElemAt、$$root、$min/$max在不同场景的应用。还涵盖了数组操作、字段删除和对象转换的相关操作符。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

$currentDate

db.getCollection('test').update({name:"shi"},{ $currentDate: {createdAt: true}})          将时间类型的一个字段修改成当前时间

$push

db.students.update({ name: "joe" }, { $push: { scores: 1 } })   在scores数组末尾添加一个元素,push只能添加一个
db.students.update(
   { name: "joe" },
   { $push: { scores: { $each: [ 90, 92, 85 ] } } }
) push添加多个需要使用$each

以前还有pushAll,现在已经被push+each代替了

$addToSet

db.inventory.update(
   { _id: 2 },
   { $addToSet: { tags: "camera" } }
 )    向一个数组添加一个元素,前提是当前数组中并没有这个元素,如果有就不添加
db.inventory.update(
   { _id: 2 },
   { $addToSet: { tags: { $each: [ "camera", "electronics", "accessories" ] } } }
 )添加多个需要使用$each操作符

$expr,  $setIsSubset   目标字段是查询参数的子集

> db.product.find()
{ "_id" : ObjectId("5d676f5f8b820718b993cd35"), "name" : 1, "vals" : [ "A", "B" ] }
{ "_id" : ObjectId("5d676fbc8b820718b993cd36"), "name" : 2, "vals" : [ "D", "C" ] }
{ "_id" : ObjectId("5d676fc98b820718b993cd37"), "name" : 3, "vals" : [ "A", "D" ] }


db.product.find( { $expr: { $setIsSubset: [ "$vals", ["A","B","D"] ] } } )   查询要求cals是["A","B","D"]的子集

结果:

{ "_id" : ObjectId("5d676f5f8b820718b993cd35"), "name" : 1, "vals" : [ "A", "B" ] }
{ "_id" : ObjectId("5d676fc98b820718b993cd37"), "name" : 3, "vals" : [ "A", "D" ] }

$where  当一个查询比较复杂的时候,没有相应的运算符,可以使用function来完成一个复杂的查询条件

db.getCollection('apis').find({$where:function() {   这个查询也是实现了被查询文档的a字段的数组是[1,2,3,4]的子集
        for (var num of this.a) {
            if(![1,2,3,4].includes(num))return false
        }
        return true;
    }})

 

$arrayElemAt        返回数组指定位置的元素

{ $arrayElemAt: [ [ 1, 2, 3 ], 0 ] }  返回1

{ $arrayElemAt: [ [ 1, 2, 3 ], -2 ] }  返回2

{ $arrayElemAt: [ [ 1, 2, 3 ], 15 ] } 数组越界无返回

{ "_id" : 1, "name" : "dave123", favorites: [ "chocolate", "cake", "butter", "apples" ] }
{ "_id" : 2, "name" : "li", favorites: [ "apples", "pudding", "pie" ] }
{ "_id" : 3, "name" : "ahn", favorites: [ "pears", "pecans", "chocolate", "cherries" ] }
{ "_id" : 4, "name" : "ty", favorites: [ "ice cream" ] }
db.users.aggregate([
   {
     $project:
      {
         name: 1,
         first: { $arrayElemAt: [ "$favorites", 0 ] },
         last: { $arrayElemAt: [ "$favorites", -1 ] }
      }
   }
])
{ "_id" : 1, "name" : "dave123", "first" : "chocolate", "last" : "apples" }
{ "_id" : 2, "name" : "li", "first" : "apples", "last" : "pie" }
{ "_id" : 3, "name" : "ahn", "first" : "pears", "last" : "cherries" }
{ "_id" : 4, "name" : "ty", "first" : "ice cream", "last" : "ice cream" }

$$root   引用当前管道处理的顶级文档,下面看例子

{ "_id" : 8751, "title" : "The Banquet", "author" : "Dante", "copies" : 2 }
{ "_id" : 8752, "title" : "Divine Comedy", "author" : "Dante", "copies" : 1 }
{ "_id" : 8645, "title" : "Eclogues", "author" : "Dante", "copies" : 2 }
{ "_id" : 7000, "title" : "The Odyssey", "author" : "Homer", "copies" : 10 }
{ "_id" : 7020, "title" : "Iliad", "author" : "Homer", "copies" : 10 }
db.books.aggregate(
   [
     { $group : { _id : "$author", books: { $push: "$$ROOT" } } }
   ]
)

先按照author分组两组,此处的$$root取出每一组的文档push到book中,结果如下:

{
  "_id" : "Homer",
  "books" :
     [
       { "_id" : 7000, "title" : "The Odyssey", "author" : "Homer", "copies" : 10 },
       { "_id" : 7020, "title" : "Iliad", "author" : "Homer", "copies" : 10 }
     ]
}

{
  "_id" : "Dante",
  "books" :
     [
       { "_id" : 8751, "title" : "The Banquet", "author" : "Dante", "copies" : 2 },
       { "_id" : 8752, "title" : "Divine Comedy", "author" : "Dante", "copies" : 1 },
       { "_id" : 8645, "title" : "Eclogues", "author" : "Dante", "copies" : 2 }
     ]
}

 

$min,max    在aggregate中和update中是不一样的

在aggregate中的使用

{ "_id": 1, "quizzes": [ 10, 6, 7 ], "labs": [ 5, 8 ], "final": 80, "midterm": 75 }
{ "_id": 2, "quizzes": [ 9, 10 ], "labs": [ 8, 8 ], "final": 95, "midterm": 80 }
{ "_id": 3, "quizzes": [ 4, 5, 5 ], "labs": [ 6, 5 ], "final": 78, "midterm": 70 }
db.students.aggregate([
   { $project: { quizMin: { $min: "$quizzes"}, labMin: { $min: "$labs" }, examMin: { $min: [ "$final", "$midterm" ] } } }
])
{ "_id" : 1, "quizMin" : 6, "labMin" : 5, "examMin" : 75 }
{ "_id" : 2, "quizMin" : 9, "labMin" : 8, "examMin" : 80 }
{ "_id" : 3, "quizMin" : 4, "labMin" : 5, "examMin" : 70 }

max 和min的用法一样,只不过是好到数组中的最大

在update中使用:

{ _id: 1, highScore: 800, lowScore: 200 }
db.scores.update( { _id: 1 }, { $max: { highScore: 950 } } )   在950和800中选出最大的跟新给highScore
{ _id: 1, highScore: 950, lowScore: 200 }

min和max的用法一样,选出最小的值跟新到指定字段。

$unset用户删除文档中的属性

删除一个直接的属性,删除文档中的quantity和instock属性,直接就没了,这两个属性

db.products.update(
   { sku: "unknown" },
   { $unset: { quantity: "", instock: "" } }
)

删除一个嵌套的属性

如果文档的quantity属性是一个object{a:1,b:2}

要删除quantity属性中的a属性,那么可以直接

db.products.update( { sku: "unknown" }, { $unset: { quantity.a: "", instock: "" } } )

删除数组中的属性

{
    "_id" : 235399,
    "casts" : {
        "crew" : [ 
            {
                "_id" : 1186343,
                "withBase" : true,
                "department" : "Directing",
                "job" : "Director",
                "name" : "Connie Rasinski"
            },
            {
                "_id" : 86342,
                "withBase" : true
            }
        ]
    },
    "likes" : 0,
    "rating" : 0,
    "rating_count" : 0,
    "release_date" : "1955-11-11"
}

删除上面文档中crew数组中的每一个item的withBase属性可以调用

 db.coll.update( {_id:235399}, {$unset: {"casts.crew.$[].withBase":""}} )

$first

返回一个组的第一个指定的值,一般跟在sort之后

{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-01-01T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-02-03T09:00:00Z") }
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-03T09:05:00Z") }
{ "_id" : 4, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-02-15T08:00:00Z") }
{ "_id" : 5, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T09:05:00Z") }
{ "_id" : 6, "item" : "xyz", "price" : 5, "quantity" : 5, "date" : ISODate("2014-02-15T12:05:10Z") }
{ "_id" : 7, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-02-15T14:12:12Z") }
db.sales.aggregate(
   [
     { $sort: { item: 1, date: 1 } },
     {
       $group:
         {
           _id: "$item",
           firstSalesDate: { $first: "$date" }
         }
     }
   ]
)
{ "_id" : "xyz", "firstSalesDate" : ISODate("2014-02-03T09:05:00Z") }
{ "_id" : "jkl", "firstSalesDate" : ISODate("2014-02-03T09:00:00Z") }
{ "_id" : "abc", "firstSalesDate" : ISODate("2014-01-01T08:00:00Z") }

$concatArrays

连接两个数组,如果出现null或者字段缺失,那么连接后的结果也是null

{ "_id" : 1, instock: [ "chocolate" ], ordered: [ "butter", "apples" ] }
{ "_id" : 2, instock: [ "apples", "pudding", "pie" ] }
{ "_id" : 3, instock: [ "pears", "pecans"], ordered: [ "cherries" ] }
{ "_id" : 4, instock: [ "ice cream" ], ordered: [ ] }
db.warehouses.aggregate([
   { $project: { items: { $concatArrays: [ "$instock", "$ordered" ] } } }
])
{ "_id" : 1, "items" : [ "chocolate", "butter", "apples" ] }
{ "_id" : 2, "items" : null }
{ "_id" : 3, "items" : [ "pears", "pecans", "cherries" ] }
{ "_id" : 4, "items" : [ "ice cream" ] }
$concat

连接两个字符串,如果字段缺失或者null,则返回null

{ "_id" : 1, "item" : "ABC1", quarter: "13Q1", "description" : "product 1" }
{ "_id" : 2, "item" : "ABC2", quarter: "13Q4", "description" : "product 2" }
{ "_id" : 3, "item" : "XYZ1", quarter: "14Q2", "description" : null }
db.inventory.aggregate(
   [
      { $project: { itemDescription: { $concat: [ "$item", " - ", "$description" ] } } }
   ]
)
{ "_id" : 1, "itemDescription" : "ABC1 - product 1" }
{ "_id" : 2, "itemDescription" : "ABC2 - product 2" }
{ "_id" : 3, "itemDescription" : null }

$ifnull

判断指定字段是否存在或者为null,如果是则替换为指定值,如果不是则直接返回

{ "_id" : 1, "item" : "abc1", description: "product 1", qty: 300 }
{ "_id" : 2, "item" : "abc2", description: null, qty: 200 }
{ "_id" : 3, "item" : "xyz1", qty: 250 }
db.inventory.aggregate(
   [
      {
         $project: {
            item: 1,
            description: { $ifNull: [ "$description", "Unspecified" ] }
         }
      }
   ]
)

{ "_id" : 1, "item" : "abc1", "description" : "product 1" }
{ "_id" : 2, "item" : "abc2", "description" : "Unspecified" }
{ "_id" : 3, "item" : "xyz1", "description" : "Unspecified" }

$literal

不做任何的计算和转化,直接返回值

{ $literal: { $add: [ 2, 3 ] } }    ==》 { "$add" : [ 2, 3 ] }
{ $literal:  { $literal: 1 } }       ==》 { "$literal" : 1 }
eg1:
{ "_id" : 2, "item" : "xyz123", price: "1" }
{ "_id" : 3, "item" : "ijk123", price: "$1" }

db.records.aggregate( [ { $project: { costsOneDollar: { $eq: [ "$price", { $literal: "$1" } ] } } } ] )

{ "_id" : 1, "costsOneDollar" : false }
{ "_id" : 2, "costsOneDollar" : false }
{ "_id" : 3, "costsOneDollar" : true }
eg2:
{ "_id" : 1, "item" : "abc123", condition: "new" }
{ "_id" : 2, "item" : "xyz123", condition: "new" }
db.bids.aggregate( [
   { $project: { item: 1, startAt: { $literal: 1 } } }
] )
{ "_id" : 1, "item" : "abc123", "startAt" : 1 }
{ "_id" : 2, "item" : "xyz123", "startAt" : 1 }

$addFields

给文档添加一个字段或者修改已存在的字段的值

添加字段:

{
  _id: 1,
  student: "Maya",
  homework: [ 10, 5, 10 ],
  quiz: [ 10, 8 ],
  extraCredit: 0
}
{
  _id: 2,
  student: "Ryan",
  homework: [ 5, 6, 5 ],
  quiz: [ 8, 8 ],
  extraCredit: 8
}
db.scores.aggregate( [
   {
     $addFields: {
       totalHomework: { $sum: "$homework" } ,
       totalQuiz: { $sum: "$quiz" }
     }
   },
   {
     $addFields: { totalScore:
       { $add: [ "$totalHomework", "$totalQuiz", "$extraCredit" ] } }
   }
] )
{
  "_id" : 1,
  "student" : "Maya",
  "homework" : [ 10, 5, 10 ],
  "quiz" : [ 10, 8 ],
  "extraCredit" : 0,
  "totalHomework" : 25,
  "totalQuiz" : 18,
  "totalScore" : 43
}
{
  "_id" : 2,
  "student" : "Ryan",
  "homework" : [ 5, 6, 5 ],
  "quiz" : [ 8, 8 ],
  "extraCredit" : 8,
  "totalHomework" : 16,
  "totalQuiz" : 16,
  "totalScore" : 40
}

添加内嵌文档的字段

{ _id: 1, type: "car", specs: { doors: 4, wheels: 4 } }
{ _id: 2, type: "motorcycle", specs: { doors: 0, wheels: 2 } }
{ _id: 3, type: "jet ski" }
db.vehicles.aggregate( [
        {
           $addFields: {
              "specs.fuel_type": "unleaded"
           }
        }
   ] )
{ _id: 1, type: "car",
   specs: { doors: 4, wheels: 4, fuel_type: "unleaded" } }
{ _id: 2, type: "motorcycle",
   specs: { doors: 0, wheels: 2, fuel_type: "unleaded" } }
{ _id: 3, type: "jet ski",
   specs: { fuel_type: "unleaded" } }

修改字段:

{ _id: 1, dogs: 10, cats: 15 }
db.animals.aggregate( [
  {
    $addFields: { "cats": 20 }
  }
] )
{ _id: 1, dogs: 10, cats: 20 }

$arrayToObject

将一个array转化成一个object

被转换的array只支持两种形式

  • [ [ "item", "abc123"], [ "qty", 25 ] ]     转化成{ "item" : "abc123", "qty" : 25 }

- OR -

[ { "k": "item", "v": "abc123"}, { "k": "qty", "v": 25 } ] 转化成{ "item" : "abc123", "qty" : 25 }
例子:
{ "_id" : 2, "item" : "ABC2",  dimensions: [ [ "l", 50 ], [ "w",  25 ], [ "uom", "cm" ] ] }
{ "_id" : 3, "item" : "ABC3",  dimensions: [ [ "l", 25 ], [ "l",  "cm" ], [ "l", 50 ] ] }
db.inventory.aggregate(
   [
      {
         $project: {
            item: 1,
            dimensions: { $arrayToObject: "$dimensions" }
         }
      }
   ]
)
{ "_id" : 1, "item" : "ABC1", "dimensions" : { "l" : 25, "w" : 10, "uom" : "cm" } }
{ "_id" : 2, "item" : "ABC2", "dimensions" : { "l" : 50, "w" : 25, "uom" : "cm" } }
{ "_id" : 3, "item" : "ABC3", "dimensions" : { "l" : 50 } }

$objectToArray

将一个object转化成一个数组

{ $objectToArray: { item: "foo", qty: 25 } }
[
   {
      "k" : "item",
      "v" : "foo"
   },
   {
      "k" : "qty",
      "v" : 25
   }
]
{ $objectToArray: {
    item: "foo",
    qty: 25,
    size: { len: 25, w: 10, uom: "cm" }
 } }
[
   {
      "k" : "item",
      "v" : "foo"
   },
   {
      "k" : "qty",
      "v" : 25
   },
   {
      "k" : "size",
      "v" : {
         "len" : 25,
         "w" : 10,
         "uom" : "cm"
      }
   }
]
{ "_id" : 1, "item" : "ABC1",  dimensions: { l: 25, w: 10, uom: "cm" } }
{ "_id" : 2, "item" : "ABC2",  dimensions: { l: 50, w: 25, uom: "cm" } }
{ "_id" : 3, "item" : "XYZ1",  dimensions: { l: 70, w: 75, uom: "cm" } }
db.inventory.aggregate(
   [
      {
         $project: {
            item: 1,
            dimensions: { $objectToArray: "$dimensions" }
         }
      }
   ]
)
{ "_id" : 1, "item" : "ABC1", "dimensions" : [ { "k" : "l", "v" : 25 }, { "k" : "w", "v" : 10 }, { "k" : "uom", "v" : "cm" } ] }
{ "_id" : 2, "item" : "ABC2", "dimensions" : [ { "k" : "l", "v" : 50 }, { "k" : "w", "v" : 25 }, { "k" : "uom", "v" : "cm" } ] }
{ "_id" : 3, "item" : "XYZ1", "dimensions" : [ { "k" : "l", "v" : 70 }, { "k" : "w", "v" : 75 }, { "k" : "uom", "v" : "cm" } ] }

$mergeObjects

将多个objects组合成一个

{ $mergeObjects: [ { a: 1 }, null ] }
{ a: 1 }
{ $mergeObjects: [ null, null ] }
{ }
{
   $mergeObjects: [
      { a: 1 },
      { a: 2, b: 2 },
      { a: 3, c: 3 }
   ]
}
{ a: 3, b: 2, c: 3 }
{
  $mergeObjects: [
    { a: 1 },
    { a: 2, b: 2 },
    { a: 3, b: null, c: 3 }
  ]
}
{ a: 3, b: null, c: 3 }

$replaceRoot

$replaceWith

这两个其实意思是一样的replaceWith是replaceRoot的别名,用指定文档替换当前文档

{ "_id" : 1, "name" : "Arlene", "age" : 34, "pets" : { "dogs" : 2, "cats" : 1 } }
{ "_id" : 2, "name" : "Sam", "age" : 41, "pets" : { "cats" : 1, "fish" : 3 } }
{ "_id" : 3, "name" : "Maria", "age" : 25 }
db.people.aggregate( [
   { $replaceRoot: { newRoot: { $mergeObjects:  [ { dogs: 0, cats: 0, birds: 0, fish: 0 }, "$pets" ] }} }
] )
{ "dogs" : 2, "cats" : 1, "birds" : 0, "fish" : 0 }
{ "dogs" : 0, "cats" : 1, "birds" : 0, "fish" : 3 }
{ "dogs" : 0, "cats" : 0, "birds" : 0, "fish" : 0 }

$out

将结果插入指定的collection中

{ "_id" : 8751, "title" : "The Banquet", "author" : "Dante", "copies" : 2 }
{ "_id" : 8752, "title" : "Divine Comedy", "author" : "Dante", "copies" : 1 }
{ "_id" : 8645, "title" : "Eclogues", "author" : "Dante", "copies" : 2 }
{ "_id" : 7000, "title" : "The Odyssey", "author" : "Homer", "copies" : 10 }
{ "_id" : 7020, "title" : "Iliad", "author" : "Homer", "copies" : 10 }
db.books.aggregate( [
                      { $group : { _id : "$author", books: { $push: "$title" } } },
                      { $out : "authors" }
                  ] )
author collection:
{ "_id" : "Homer", "books" : [ "The Odyssey", "Iliad" ] }
{ "_id" : "Dante", "books" : [ "The Banquet", "Divine Comedy", "Eclogues" ] }

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值