mongodb简单用法

时间:2023-03-10 03:38:02
mongodb简单用法

修改器:

$inc: 增加已有的键值,如果键值不存在就创建一个

数据库中存在这样的数据:
{
"_id" : ,
"url": "www.example.com",
"count" :
}
db.fzk.update({"url" : "www.example.com"}, {"$inc" : {"count" : 1}})

$set     :  指定一个字段的值,如果字段不存在那么就创建它,还可以修改键对应值的类型
$unset : 将这个键可以完全删掉
$push  : 向已有的数组的末位增加一个元素,如果没有就创建一个新的数组
$each  : 可以一次$push 多个数据,下面向数组中放置了两个值。

db.fzk.update(
{"_id" : },
{"$push": {"type": {"$each" : ["java", "python"]}}}
)

$slice : 限制数组的长度,接负整数。可以与$each搭配使用。

db.fzk.update(
{"_id" : },
{"$push": {"top10": {"$each" : ["java", "python"],
"$slice" : "-10"}}}
)

  如果小于10,全部保留,如果大于10,只保留最后的10个元素。$slice后跟的只能是负整数
$ne    : 将数组作为数据集合使用,保证数组内的元素不会重复。

db.fzk.update(
{"namelist" : {"$ne" : "fzk" }},
{"$push": {"namelist": "fzk"}}
)

$addToSet :  有些情况$ne使用不了就需要使用$addToSet $addToSet可以和$each一起使用,$ne就不可以

db.fzk.update(
{"_id" : 0},
{"$addToSet": {"namelist": "fzk"}}
)

$pop    : 从数组的任意一端删除元素

{$pop : { "key" : -} }  从数组头部删除一个元素
{$pop : { "key" : } }  从数组末尾删除一个元素

$pull    : 根据特定条件删除元素

db.lists.insert({"todo" : ["dishes", "laundry", "dry"]})
db.lists.update({}, {"$pull" : {"todo" : "laundry"}})

基于位置的数组修改器  : 数组下标获取 $

db.blob.update({"post" : "post_id"}, {"$inc" : {"comments.0.votes" : }})
db.blob.update({"author" : "john"}, {"$set" : {"comments.$.author" : "jim"}}) $通过匹配的进行修改

upsert : 没有找到某个文档会创建一个新的文档,第三个参数为true表示upsert。

db.fzk.update({}, {}, true)

$setOnInsert : 创建的时候需要赋值,但是之后所有更新操作中,这个字段的值都不在改变。

db.users.update({}, {"$setOnInsert" : {"createdAt" : "new Date()"}}, true)
db.users.update({}, {"$setOnInsert" : {"createdAt" : "new Date()"}}, true) 第二次运行的时候会发现createAt字段没有改变。还是插入时候的值

多对个文档进行修改 : 默认情况下,update只会修改一个文档,当第四个参数设置为true后,会对所有匹配的文档进行修改

db.users.update({"_id" : }, {"$set" : {"gift" : "happy"}}, false, true)

findAndMofify  :

ps = db.runCommend({"findAndMofify" : "processes",                 #processes 集合名
"query" : {"status" : "READY"}, #query查询的条件
"sort" : {"priority" : -}, #排序结果的条件
"update" : {"$set" : {"status" : "RUNNING"}} #更新成
})

  findAndMofify:字符串,集合名
    query:查询文档
    sort:排序结果
    update: 修改器文档
    remove:布尔类型,表示是否删除文档
    new : 布尔类型,表示返回更新前的文档还是更新后的文档,默认更新前的
    fileds : 文档中需要返回的字段
    upsert : 布尔类型,值为true表示是一个upsert,默认false
    update 和 remove 必须有一个,也只能有一个,如果没有这个命令会报错。

消除指定的键 : find或findOne指定第二个参数指定返回的键,但是_id总是返回。可以利用 _id : 0 把_id剔除掉

db.users.find({}, {"username" : , "email" : })
{
  "_id" : ObjectId("4ba0f0dfd22aa494fd523620"),
  "username" : "joe",
  "email" : "joe@example.com"
}
db.users.find({}, {"username" : , "_id" : })
{
  "username" : "joe",
}

$lt、 $lte、 $gt、 $gte分别对应<、 <=、 >、 >=

db.users.find({"age" : {"$gte" : , "$lte" : }})

$or $in $nin

db.raffle.find({"ticket_no" : {"$in" : [, , ]}})
db.raffle.find({"ticket_no" : {"$nin" : [, , ]}})
db.raffle.find({"$or" : [{"ticket_no" : }, {"winner" : true}]})
db.raffle.find({"$or" : [{"ticket_no" : {"$in" : [, , ]}}, {"winner" : true}]})

$not $mod(取模)

db.users.find({"id_num" : {"$mod" : [, ]}})             #1 6 11 16
db.users.find({"id_num" : {"$not" : {"$mod" : [, ]}}})

null : 即会匹配本身为null的数据,又会匹配其他文档不包含这个字段的数据。用exists消除不包含的字段

db.c.find({"z" : {"$in" : [null], "$exists" : true}})       #使用in看起来很不舒服,但是没有$eq操作符

正则  : MongoDB使用Perl兼容的正则表达式(PCRE)库来匹配正则表达式

db.users.find({"name" : /joe/i})      #i是正则表达式标志,可有可无
db.foo.insert({"bar" : /baz/})     #支持正则表达式匹配,就是数据库存的就是正则表达式
db.foo.find({"bar" : /baz/})

数组查询

db.food.insert({"fruit" : ["apple", "banana", "peach"]})
db.food.find({"fruit" : "banana"}) db.food.insert({"_id" : , "fruit" : ["apple", "banana", "peach"]})
db.food.insert({"_id" : , "fruit" : ["apple", "kumquat", "orange"]})
db.food.insert({"_id" : , "fruit" : ["cherry", "banana", "apple"]})
# $all会匹配一组元素
db.food.find({fruit : {$all : ["apple", "banana"]}}) # _id=1 _id=3会匹配

{fruit : {$all : ['apple']}和{fruit : 'apple'} #查询结果完成一样 db.food.find({"fruit" : ["apple", "banana"]}) #精确匹配,必须一致,这个不会匹配任何一条 db.food.find({"fruit.2" : "peach"}) #可以利用数组下标匹配

$size  :  查询特定长度的数组,但是$size并不能并不能与其他查询条件(eg:$gt)组合使用

db.food.find({"fruit" : {"$size" : }})

$slice  :

db.blog.posts.findOne(criteria, {"comments" : {"$slice" : }})           #头十条
db.blog.posts.findOne(criteria, {"comments" : {"$slice" : -}}) #后十条
db.blog.posts.findOne(criteria, {"comments" : {"$slice" : [, ]}}) #从第24条开始取到33条,不够33返回24后所有的 db.blog.posts.findOne(criteria, {"comments" : {"$slice" : -}}) #$slice 默认会返回文档的所有键 下面title和content都返回了
结果:{
"_id" : ObjectId("4b2d75476cc613d5ee930164"),
"title" : "A blog post",
"content" : "...",
"comments" : [
{
"name" : "bob",
"email" : "bob@example.com",
"content" : "good post."
}
]
}

db.blog.posts.find({"comments.name" : "bob"}, {"comments.$" : 1})        # $操作符得到一个匹配的元素,但是这样只会返回第一个匹配的文档,如果有多条comments,只有第一条会返回
 {
  "_id" : ObjectId("4b2d75476cc613d5ee930164"),
  "comments" : [
    {
      "name" : "bob",
      "email" : "bob@example.com",
      "content" : "good post."
   }
    ]
  }

 

数组和范围查询

{"x" : }
{"x" : }
{"x" : }
{"x" : [, ]}
> db.test.find({"x" : {"$gt" : , "$lt" : }})      #会返回两条数据 因为5小于20,25大于10
{"x" : }
{"x" : [, ]} > db.test.find({"x" : {"$elemMatch" : {"$gt" : 10, "$lt" : 20}})    #没有结果匹配,因为15不是一个数组 # 如果当前查询的字段上创建过索引,现在这个查询只会遍历位于10和20之间的索引,不在与5和25比较。只有当前查询的字段上建立过索引时,才可以使用ming()和max(),而且必须为这个索引的所有字段指定min和max
> db.test.find({"x" : {"$gt" : 10, "$lt" : 20}).min({"x" : 10}).max({"x" : 20})
{"x" : 15}

查询内嵌文档

{
  "name" : {
    "first" : "Joe",
    "last" : "Schmoe"
  },
  "age" :
}
> db.people.find({"name" : {"first" : "Joe", "last" : "Schmoe"}})  # 可以匹配,但是这个和顺序还有关系,如果first和last调换位置,就不能匹配
> db.people.find({"name.first" : "Joe", "name.last" : "Schmoe"})

> db.blog.find()
  {
    "content" : "...",
    "comments" : [
    {
      "author" : "joe",
      "score" : 3,
      "comment" : "nice post"
    },
    {
      "author" : "mary",
      "score" : 6,
      "comment" : "terrible post"
    }
    ]
  }

 > db.blog.find({"comments" : {"author" : "joe","score" : {"$gte" : 5}}})    #这种方法不对,joe会匹配第一个,$gte : 5会匹配第二个,所以返回值还是这个文档
  > db.blog.find({"comments" : {"$elemMatch" : {"author" : "joe", "score" : {"$gte" : 5}}}})      #正确写法

$where

> db.foo.insert({"apple" : , "banana" : , "peach" : })
> db.foo.insert({"apple" : , "spinach" : , "watermelon" : })
#想获取两个键具有相同值的文档
> db.foo.find({"$where" : function () {
... for (var current in this) {
...  for (var other in this) {
...    if (current != other && this[current] == this[other]) {
...      return true;
...    }
...  }
... }
... return false;
... }});

  如果true,文档就作为结果集的一部分返回,如果false,就不返回。

高级查询选项       $maxscan    $min     $max    $showDiskLoc

> db.foo.find(criteria)._addSpecial("$maxscan", )  #指定扫描文档数量的上限
> db.foo.find()._addSpecial('$showDiskLoc',true) #返回该条记录在磁盘的位置

获取一致结果  快照(需要知道mongodb的存储过程)

> db.foo.find().snapshot()

唯一索引

> db.users.ensureIndex({"username" : }, {"unique" : true})
> db.people.ensureIndex({"username" : 1}, {"unique" : true, "dropDups" : true})    #dropDups在创建索引时会删除索引重复的文档,并不知道会是哪一个,慎重

sparse :   唯一索引会把null看做值,所以无法将多个缺少唯一索引中的键的文档插入到一个集合里。sparse是这个字段可能存在可能不存在,当这个键存在时必须是唯一的

#创建稀松索引语法   
> db.ensureIndex({"email" : 1}, {"unique" : true, "sparse" : true}) #用unique和sparse组合可以达到如果存在这个键,键对应的值就比需是唯一的目的
> db.ensureIndex({"email" : 1}, {"sparse" : true}) # sparse可以不是唯一的
> db.foo.find()
{ "_id" : }
{ "_id" : , "x" : }
{ "_id" : , "x" : }
{ "_id" : , "x" : }

> db.foo.find({"x" : {"$ne" : 2}})   #没有sparse index

  { "_id" : 0 }
  { "_id" : 1, "x" : 1 }
  { "_id" : 2, "x" : 2 }
  { "_id" : 3, "x" : 3 }

> db.foo.find({"x" : {"$ne" : 2}})   #x上建了sparse index时   _id为0的没有查到  如果还想要这样的数据,需要hint()进行全盘扫描
  { "_id" : 1, "x" : 1 }
  { "_id" : 3, "x" : 3 }

强制全盘扫描

> db.entries.find({"created_at" : {"$lt" : hourAgo}}).hint({"$natural" : })

删除索引

db.people.dropIndex("x_1_y_1")           #是根据索引名删除
db.people.getIndexes() #查看所有索引信息

固定集合

> db.createCollection("my_collection", {"capped" : true, "size" : });
> db.createCollection("my_collection2", {"capped" : true, "size" : 100000, "max" : 100}); #创建名为my_collection2的集合,大小100000字节,最多100条文档
> db.runCommand({"convertToCapped" : "test", "size" : 10000}); #将非固定集合转为固定集合
> db.my_collection.find().sort({"$natural" : -1}) #固定集合的自然排序就是文档的插入顺序

TTL索引(time-to-live index)

> db.foo.ensureIndex({"lastUpdated" : }, {"expireAfterSecs" : **})                  #lastUpdated超过预计时间这条文档就删除

聚合

> db.articles.aggregate({"$project" : {"author" : }},            #将author和_id投射出来
... {"$group" : {"_id" : "$author", "count" : {"$sum" : }}}, #将_id的值设为author的值,没出现一次count +1
... {"$sort" : {"count" : -}},                          # 将count降序排序
... {"$limit" : })                                 #取前五条数据 $match  对文档进行筛选
  可与所有常规操作符连用($gt/$lt/$in等)
  用法:{$match : {"state" : "usa"}} $project从子文档中提取字段
  db.users.aggregate({"$project" : {"userId" : "$_id", "_id" : 0}})    #注意$_id,可以使用$fieldname代替文档中的字符值
  1.管道表达式
    最简单的是$fieldname,也可以将多个字面量组合
  2.数学表达式
    "$add" : [expr1[, expr2, ..., exprN]]      加
    "$subtract" : [expr1, expr2]            减
    "$multiply" : [expr1[, expr2, ..., exprN]]   乘
    "$divide" : [expr1, expr2]             除
    "$mod" : [expr1, expr2]               取余
  用法:    

    > db.employees.aggregate(
    ... {
    ...  "$project" : {
    ...    "totalPay" : {
    ...      "$subtract" : [{"$add" : ["$salary", "$bonus"]}, "$401k"]
    ...    }
    ...  }
    ... })

  3.日期表达式
    "$year" , "$month" , "$week" ,"$dayOfMonth" , "$dayOfWeek" , "$dayOfYear" , "$hour" , "$minute" , "$second"
    用法:

    > db.employees.aggregate(
    ... {
    ...  "$project" : {
    ...    "tenure" : {
    ...      "$subtract" : [{"$year" : new Date()}, {"$year" : "$hireDate"}]
    ...    }
    ...  }
    ... })

  4.字符串表达式
    "$substr" : [expr, startOffset, numToReturn]
    "$concat" : [expr1[, expr2, ..., exprN]]
    "$toLower" : expr
    "$toLower" : expr
    "$toUpper" : expr
    用法:一个生成 j.doe@example.com 的例子

    > db.employees.aggregate(
    ... {
    ...  "$project" : {
    ...    "email" : {
    ...      "$concat" : [
    ...        {"$substr" : ["$firstName", 0, 1]},
    ...        ".",
    ...        "$lastName",
    ...        "@example.com"
    ...      ]
    ...    }
    ...  }
    ... })

  5.逻辑表达式
    "$cmp" : [expr1, expr2]
    "$strcasecmp" : [string1, string2]
    "$eq"/"$ne"/"$gt"/"$gte"/"$lt"/"$lte" : [expr1, expr2]
    "$and" : [expr1[, expr2, ..., exprN]]
    "$or" : [expr1[, expr2, ..., exprN]]
    "$not" : expr
    "$cond" : [booleanExpr, trueExpr, falseExpr]        #booleanExpr为true就返回trueExpr,false就返回falseExpr
    "$ifNull" : [expr, replacementExpr]              #null就返回replacementExpr,否则expr

  6.一个提取的例子(老师喜欢的100分其他的 出勤10%、日常30%、期末60%)

    > db.students.aggregate(
    ... {
    ...  "$project" : {
    ...    "grade" : {
    ...      "$cond" : [
    ...        "$teachersPet",
    ...        100, // if
    ...        {// else
    ...          "$add" : [
    ...            {"$multiply" : [.1, "$attendanceAvg"]},
    ...            {"$multiply" : [.3, "$quizzAvg"]},
    ...            {"$multiply" : [.6, "$testAvg"]}
    ...          ]
    ...        }
    ...      ]
    ...    }
    ...  }
    ... })

 $group  分组

  1.分组操作符   
    可以对每个分组进行计算,比如之前的$sum

  2.算数操作符
    "$sum" 和 "$average"

  3.极值操作符
    "$max" : expr
    "$min" : expr
    "$first" : expr
    "$last" : expr

    用法:
    > db.scores.aggregate(
    ... {
    ...  "$group" : {
    ...    "_id" : "$grade",
    ...    "lowestScore" : {"$min" : "$score"},
    ...    "highestScore" : {"$max" : "$score"}
    ...  }
    ... })

  4.数组操作符
    "$addToSet" : expr
    "$push" : expr

$unwind
  拆分,数组中的每个值拆分成单独的文档

  将comments拆分出来,取到作者为Mark的comment
  > db.blog.aggregate({"$project" : {"comments" : "$comments"}},
  ... {"$unwind" : "$comments"},
  ... {"$match" : {"comments.author" : "Mark"}})

$sort

  > db.employees.aggregate(
  ... {
  ...  "$project" : {
  ...    "compensation" : {
  ...      "$add" : ["$salary", "$bonus"]
  ...    },
  ...    "name" : 1
  ...  }
  ... },
  ... {
  ...  "$sort" : {"compensation" : -1, "name" : 1}
  ... })

$limit
  取前n个文档

$skip
  跳过前n个文档