mongodb常用增刪改語句、多表關聯查詢

下載安裝mongodb參考:

https://www.runoob.com/mongodb/mongodb-window-install.html

展示所有數據庫

show dbs;

新建或進入數據庫myNewDb

use myNewDb;

展示數據myNewDb的所有表

show tables;    或者 show collections

創建一個表/集合party

db.createCollection("party");

新增記錄

db.party.insert({"_id":1,"name":"張三","age":20,"address":"蘇州"});

db.getCollection("party").insert({"name":"李四","age":21,"birth":"1997-01-01"});

查詢所有記錄(格式化)

db.party.find({}).pretty();

條件查詢,並返回指定字段之外的字段(除了name的字段)

db.party.find({"_id":1},{"name":0});

條件查詢,並返回指定字段的字段(name,address的字段)

db.party.find({"_id":1},{"name":1,"address":1});

模糊查詢,查詢name字段的值含有’張’字的記錄

db.party.find({"name":/張/})

查詢name中以‘張’爲開頭的記錄

db.party.find({"name":/^張/})

mongoDB中將某個字段(如id)升序排序查詢

db.party.find({})

 

排序(將id升序):

db.party.find({}).sort({ _id:1 })

分頁查詢(結合skip和limit函數):

db.party.find({}).sort({ _id:1 }).skip(5).limit(5)

tips:注意mongoDB分頁的時候直接使用skip是一條一條逐步跳的,當數據量過大,會引發性能上問題,可以通過條件查詢+排序+限制返回記錄,即邊查詢,邊排序,排序之後,抽取上一頁中的最後一條記錄,作爲當前分頁的查詢條件,從而避免了skip效率低下的問題

 

批量插入

db.party.insert([
    {"_id":3,"name":"小明","age":20,"address":"上海","birth":"2000-01-01"},
    {"_id":4,"name":"小紅","age":21,"address":"蘇州","birth":"1999-01-01"},
    {"_id":5,"name":"小王","age":22,"address":"北京","birth":"1999-06-01"},
    {"_id":6,"name":"小張","age":18,"address":"南京","birth":"2002-01-01"}
])

 

修改語句:

db.party.update({"_id":ObjectId("5ee0436eb55460eb7df12736")},{$set: {"name":"李四2"}})

刪除

remove方法

mongoDB多表關聯查詢

數據庫常用的查詢少不了多表關聯查詢,MongoDB在3.2版本中新增$lookup的高級查詢

1.主要功能:

將每個輸入待處理的文檔,經過$lookup 階段的處理,輸出的新文檔中會包含一個新生成的數組列(戶名可根據需要命名新key的名字 )。數組列存放的數據 是 來自 被Join 集合的適配文檔,如果沒有,集合爲空(即 爲[ ])

2.基本使用語法:

{
   $lookup:
     {
       from: <collection to join>,
       localField: <field from the input documents>,
       foreignField: <field from the documents of the "from" collection>,
       as: <output array field>
     }
}

3.語法的解釋說明

語法值

解釋說明

from

同一個數據庫下等待被Join的集合

localField

源集合中的match值,如果輸入的集合中,某文檔沒有loaclField這個key(Field),在處理的過程中,會默認爲此文檔含有localField:null的鍵值對

foreignField

待Join的集合的match值,如果待Join的集合中,文檔沒有foreignField值,在處理的過程中,會默認爲此文檔含有foreignField:null的鍵值對

as

爲輸出文檔的新增值命名。如果輸入的集合中已存在該值,則會覆蓋掉

 

語法值 解釋說明
from 同一個數據庫下等待被Join的集合
localField 源集合中的match值,如果輸入的集合中,某文檔沒有loaclField這個key(Field),在處理的過程中,會默認爲此文檔含有localField:null的鍵值對
foreignField 待Join的集合的match值,如果待Join的集合中,文檔沒有foreignField值,在處理的過程中,會默認爲此文檔含有foreignField:null的鍵值對
as 爲輸出文檔的新增值命名。如果輸入的集合中已存在該值,則會覆蓋掉

(注:null=null此爲真)

其語法語句可以類似的理解爲sql語句:

SELECT *, <output array field>
FROM collection
WHERE <output array field> IN (SELECT * FROM <collection to join> 
    WHERE <foreignField>=<collection.localField>);

舉例:

例1:

假設有訂單集合orders,存儲如下數據:

db.orders.insert([
   { "_id" : 1, "item" : "純淨水", "price" : 2, "quantity" : 2 },
   { "_id" : 2, "item" : "可樂", "price" : 3, "quantity" : 1 },
   { "_id" : 3  }
])

有商品集合goods(集合中的goodname對應訂單表中的item),存儲如下數據:

db.goods.insert([
   { "_id" : 1, "goodname" : "純淨水", description: "水是生命的源泉", "num" : 120 },
   { "_id" : 2, "goodname" : "麪包", description: "蓬鬆法式軟麪包", " num " : 80 },
   { "_id" : 3, "goodname" : "雪碧", description: "酷爽一夏", " num " : 60 },
   { "_id" : 4, "goodname" : "可樂", description: "可口可樂", " num " : 70 },
   { "_id" : 5, "goodname": null, description: "待定" },
   { "_id" : 6 }
])

在這種模式設計下,如果要查詢訂單表對應商品的信息情況:

常規的sql語句應該是:

select * from orders o left join goods g on o.item = g.goodname;

而此處是MongoDb,那麼可以寫成:

db.orders.aggregate([
    {
        $lookup: {
               from: "goods",
               localField: "item",
               foreignField: "goodname",
               as: "goods_docs"
             }
    }
])

返回的執行結果:

返回的結果json值如下:

{
	"_id" : 1,
	"item" : "純淨水",
	"price" : 2,
	"quantity" : 2,
	"goods_docs" : [
		{
			"_id" : 1,
			"goodname" : "純淨水",
			"description" : "水是生命的源泉",
			"num" : 120
		}
	]
},

/* 2 */
{
	"_id" : 2,
	"item" : "可樂",
	"price" : 3,
	"quantity" : 1,
	"goods_docs" : [
		{
			"_id" : 4,
			"goodname" : "可樂",
			"description" : "可口可樂",
			" num " : 70
		}
	]
},

/* 3 */
{
	"_id" : 3,
	"goods_docs" : [
		{
			"_id" : 5,
			"goodname" : null,
			"description" : "待定"
		},
		{
			"_id" : 6
		}
	]
}

根據上面的查詢語句以及結果,可以將上面的處理過程,描述如下:

從集合orders中逐個獲取文檔處理,拿到一個文檔後,會根據localField值遍歷被Join的goods集合(from:"goods"),看goods集合文檔中foreignField值是否與之相等。如果相等,就把符合條件的goods文檔整體內嵌到聚合框架新生成的文檔中,並且新key統一命名爲goods_docs。考慮到符合條件的文檔不唯一,這個Key對應的Value是個數組形式。原集合中Key對應的值爲Null值或不存在時,需特別注意

例2:

接下來複雜些,多表關聯後肯定有條件限制,如:

查詢訂單表中id爲1對應商品名的所對應商品庫存大於100的信息情況:

常規的sql語句應該是:

select * from orders o left join goods g on o.item = g.goodname where o.id =1 and g.num>100;

那麼對應的mongoDB的查詢語句:

db.orders.aggregate([
    {$match: {"_id":1}},
    {
        $lookup: {
               from: "goods",
               localField: "item",
               foreignField: "goodname",
               as: "goods_docs"
             }
    },
    {$match: {"goods_docs.num":{$gt: 100}}}
])

對應的結果的json值:

{
    "_id" : 1,
    "item" : "純淨水",
    "price" : 2,
    "quantity" : 2,
    "goods_docs" : [
       {
           "_id" : 1,
           "goodname" : "純淨水",
           "description" : "水是生命的源泉",
           "num" : 120
       }
    ]
}

例3:

源表(orders)中比較列爲某一個值,而此值在待比較表(goods)的所有文檔中都不存在

orders集合在現有數據的基礎上,再被insert一條記錄,這個訂單的商品爲蘇打水,在庫存商品goods集合中根本沒有此數據。

db.orders.insert(
    {"_id" : 4, "item" : "蘇打水", "price" : 3, "quantity" : 1 }
)

再次執行查詢:

select * from orders o left join goods g on o.item = g.goodname  where o.id = 4;

執行對應的mongoDB的查詢語句:

db.orders.aggregate(
    {
        $match: {"_id":4}
    },
    {
        $lookup: {
               from: "goods",
               localField: "item",
               foreignField: "goodname",
               as: "goods_docs"
             }    
    }
)

例4:

上述例子比較單一,只是單純的key/value,下面比較數組,首先先將orders以及goods集合裏的數據清空

db.orders.remove({});
db.goods.remove({});

再向orders中插入數據:

db.orders.insert(
    { "_id" : 1, "item" : "MON1003", "price" : 350, "quantity" : 2, "remark" :[ "27 inch", "Retina display", "1920x1080" ], "type" : "Monitor" }
)

注:插入的記錄中remark是數組格式

向goods插入數據:

db.goods.insert([
    { "_id" : 1, "goodname" : "MON1003", "type" : "Monitor", "num" : 120,"size" : "27 inch", "resolution" : "1920x1080" },
    { "_id" : 2, "goodname" : "MON1012", "type" : "Monitor", "num" : 85,"size" : "23 inch", "resolution" : "1280x800" },
    { "_id" : 3, "goodname" : "MON1031", "type" : "Monitor", "num" : 60,"size" : "23 inch", "display_type" : "LED" }
])

此時關聯orders中的remark與goods中的size

db.orders.aggregate([
   {
      $unwind: "$remark"
   },
   {
      $lookup:
         {
            from: "goods",
            localField: "remark",
            foreignField: "size",
            as: "goods_docs"
        }
   }
])

執行返回的結果:

根據結果可以看到{$unwind: "$specs"}將數據每個值都遍歷了,將上述查詢語句改成(條件篩選不爲空的):

db.orders.aggregate([
   {
      $unwind: "$remark"
   },
   {
      $lookup:
         {
            from: "goods",
            localField: "remark",
            foreignField: "size",
            as: "goods_docs"
        }
   },
   {$match: {"goods_docs":{$ne: []}}}
]);

執行返回的結果:

例5:

mongodb 集合間關聯後更新,藉助 forEach 功能

需求:集合orders和orderInfo關聯,篩選符合條件,然後更新orders的數據。

db.orders.aggregate([
     {$match:{"status" : 2}},
     {$match:{"disabled" : 0}},
     {$match:{"consumer" : "小王"}},
     {
     $lookup:
       {
         from: "orderInfo",
         localField: " orderId ",
         foreignField: "orderInfoId",
         as: "orderInfo_docs"
       }
  },
  { $match : {"orderInfo _docs" : [ ]} }
]).forEach(function(item){
    db.orders.update({"_id":item._id},{$set:{"status":1 }})
})

例6:

拓展一下,多張表(兩張以上關聯)的時候

舉例user(用戶),orders(訂單),products(商品)表

db.orders.aggregate([{
    $lookup:
    {
      from: "products",
      localField: "pid",
      foreignField: "_id",
      as: " products_docs"
    }
},{
    $lookup:
    {
      from: "user",
      localField: "uid",
      foreignField: "_id",
      as: "user_docs"
    }
}]);

 

最後推薦一個mongodb的桌面管理工具,官網下載地址:

https://nosqlbooster.com/downloads

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章