MongoDB

1、MongoDB概念解析:
SQL和MongoDB概念區別
2、數據庫:

"show dbs"命令可以顯示所有數據的列表。
"db"命令可以顯示當前數據庫對象或集合。
"use"命令,可以連接到一個指定的數據庫。

3、集合:
db.createCollection("mycoll", {capped:true, size:100000})  
4、元數據:
元數據
5、MongoDB數據類型:
數據類型
  • ObjectId


    ObjectId
6、創建數據庫:
use DATABASE_NAME

如果數據庫不存在,則創建數據庫,否則切換到指定數據庫。

  db.runoob.insert({"name":"菜鳥教程"})

集合只有在內容插入后才會創建
MongoDB 中默認的數據庫為 test,如果你沒有創建新的數據庫,集合將存放在 test 數據庫中。

7、刪除數據庫:
db.dropDatabase()#默認刪除test

db.collection.drop()#刪除集合
  • 例子

    >use runoob
    switched to db runoob
    >show tables
    site
    >db.site.drop()
    true
    >show tables
    >
    
8、創建集合:
db.createCollection(name, options)
  • 創建固定集合 mycol,整個集合空間大小 6142800 KB, 文檔最大個數為 10000 個。

    >db.createCollection("mycol", {capped: true, autoIndexId: true, size: 6142800, max: 10000})
    
  • 在 MongoDB 中,你不需要創建集合。當你插入一些文檔時,MongoDB 會自動創建集合。

    >db.mycol2.insert({"name":  "haha"})
    >show collections
    mycol2
    
9、刪除集合:
db.collection.drop()

#例子
db.mycol2.drop()
10、插入文檔:
db.COLLECTION_NAME.insert(document)

#例子
>db.mycol.insert({title: 'MongoDB教程', 
          description: 'MongoDB是一個Nosql數據庫',
          by: '菜鳥教程',
          url: 'http://www.runoob.com',
          tags: ['MongoDB', 'database', 'NoSQL'],
          likes: 100
})
  • 查看已插入文檔:

    db.mycol.find()
    
  • 將數據定義成一個變量

    > document=({title: 'MongoDB 教程', 
    description: 'MongoDB 是一個 Nosql 數據庫',
    by: '菜鳥教程',
    url: 'http://www.runoob.com',
    tags: ['mongodb', 'database', 'NoSQL'],
    likes: 100
    });
    
    >db.mycol.insert(document)
    
    >db.mycol.save(document)
    
11、更新文檔:
  • update()方法

    db.collection.update(
       <query>,
       <update>,
       {
         upsert: <boolean>,
         multi: <boolean>,
         writeConcern: <document>
       }
    )
      query : update的查詢條件,類似sql update查詢內where后面的。
      update : update的對象和一些更新的操作符(如$,$inc...)等,也可以理解為sql update查詢內set后面的
      upsert : 可選,這個參數的意思是,如果不存在update的記錄,是否插入objNew,true為插入,默認是false,不插入。
      multi : 可選,mongodb 默認是false,只更新找到的第一條記錄,如果這個參數為true,就把按條件查出來多條記錄全部更新。
      writeConcern :可選,拋出異常的級別。
    
  • 實例

    #將標題“MongoDB教程”改為“MongoDB”。
    >db.mycol.update({'title': 'MongoDB教程'}, {$set: {'title': 'MongoDB'}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })   # 輸出信息
    >db.mycol.find().pretty()
    {
            "_id" : ObjectId("56064f89ade2f21f36b03136"),
            "title" : "MongoDB",
            "description" : "MongoDB 是一個 Nosql 數據庫",
            "by" : "菜鳥教程",
            "url" : "http://www.runoob.com",
            "tags" : [
                    "mongodb",
                    "database",
                    "NoSQL"
              ],
            "likes" : 100
    }
    >
    >db.mycol.update({'title': 'MongoDB教程'}, {$set: {'title': 'MongoDB'}}, {multi: true})
    
  • save()方法

    db.collection.save(
       <document>,
       {
         writeConcern: <document>
       }
    )
      document : 文檔數據。
      writeConcern :可選,拋出異常的級別。
    
  • 推薦使用

    db.collection.updateOne() #更新單個文檔
    db.collection.updateMany() #更新多個文檔
    
10、刪除文檔:
  db.collection.remove(
     <query>,
     {
       justOne: <boolean>,
       writeConcern: <document>
     }
  )
    query :(可選)刪除的文檔的條件。
    justOne : (可選)如果設為 true 或 1,則只刪除一個文檔。
    writeConcern :(可選)拋出異常的級別。
  • 實例

    > db.col.find()
    { "_id" : ObjectId("56066169ade2f21f36b03137"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "菜鳥教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
    { "_id" : ObjectId("5606616dade2f21f36b03138"), "title" : "MongoDB 教程", "description" : "MongoDB 是一個 Nosql 數據庫", "by" : "菜鳥教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
    #移除
    >db.mycol.remove({'title': 'MongoDB 教程'})
    WriteResult({ "nRemoved" : 2 })           # 刪除了兩條數據
    
    #刪除所有數據
    >db.col.remove({})
    >db.col.find()
    >  
    
  • 推薦使用

    >db.inventory.deleteMany({})  #刪除全部文檔
    >db.inventory.deleteMany({status: 'A'}) #刪除status=A的全部文檔
    >db.inventory.deleteOne({status: 'D'}) #刪除status=D的一個文檔
    
11、查詢文檔:
  db.collection.find(query, projection)
    query :可選,使用查詢操作符指定查詢條件
    projection :可選,使用投影操作符指定返回的鍵。查詢時返回文檔中所有鍵值, 只需省略該參數即可(默認省略)。
  • 易讀的方式

    >db.collection.find().pretty() #格式化顯示所有文檔
    
  • MongoDB與RDBMS where語句比較:


  • AND條件

    >db.collection.find({key1: value1, key2: value2}).pretty()
    >db.mycol.find({'by': '菜鳥教程', 'title': 'MongoDB 教程'}).pretty()
    
  • OR條件

    >db.collection.find({$or: [{'by': '菜鳥教程'}, {'title': 'MongoDB 教程'}]}).pretty()
    
  • AND和OR聯合使用

    >db.collection.find({'likes': {$gt: 50}, $or: [{'by': '菜鳥教程'}, {'title': 'MongoDB 教程'}]}).pretty()
    
  • projection參數使用方法

    #若不指定 projection,則默認返回所有鍵,指定 projection 格式如下,有兩種模式
    db.collection.find(query, {title: 1, by: 1}) // inclusion模式 指定返回的鍵,不返回其他鍵
    db.collection.find(query, {title: 0, by: 0}) // exclusion模式 指定不返回的鍵,返回其他鍵
    
12、條件操作符:
  • (>) 大于 - $gt   greater than

  • (<) 小于 - $lt    less than

  • (>=) 大于等于 - $gte

  • (<= ) 小于等于 - $lte

    db.collection.find({likes: {$gt: 100}})
    #Select * from collection where likes >=100;
    db.collection.find({likes: {$lte: 150}})
    
  • 模糊查詢

    #查詢包含“教”字的文檔
    db.collection.find({title: /教/})
    #查詢以“教”字開頭的文檔
    db.collection.find({title: /^教/})
    #查詢以“教”字結尾的文檔
    db.collection.find({title: /教$/})
    
13、$type操作符:
MongoDB中的類型
#獲取集合中title為字符串的數據
>db.collection.find({'title': {$type: 2}})
>db.collection.find({'title': {$type: 'string'}})
15、Limit與Skip方法:
  • Limit()方法:指定數據記錄的數量

    >db.COLLECTION_NAME.find().limit(NUMBER)
    
    
    舉例
    #第一個 {} 放 where 條件,為空表示返回集合中所有文檔。
    #第二個 {} 指定那些列顯示和不顯示 (0表示不顯示 1表示顯示)。
    >db.collection.find({}, {'title': 1, _id: 0}).limit(2) 
    { "title" : "PHP 教程" }
    { "title" : "Java 教程" }
    >
    
  • Skip()方法:跳過指定數量的數據

    >db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)
    
    
    舉例
    >db.collection.find({}, {'title': 1, _id: 0}).limit(1).skip(1) #skip默認參數為0
    { "title" : "Java 教程" }
    >
    
  • Limit() 和Skip()聯合舉例

    #想要讀取從 10 條記錄后 100 條記錄,相當于 sql 中limit (10,100)。
    >db.COLLECTION_NAME.find().skip(10).limit(100)
    
    #假設查詢第100001條數據,這條數據的Amount值是:2399927,
    >db.test.sort({"amount":1}).skip(100000).limit(10)  //183ms
    >db.test.find({amount:{$gt:2399927}}).sort({"amount":1}).limit(10)  //53ms
    >
    
16、排序Sort()方法:
# 通過使用1和-1來指定排序的方式
>db.COLLECTION_NAME.find().sort({KEY: 1})

#舉例
>db.collection.find({}, {'title': 1,  _id: 0}).sort({'likes': -1})
{ "title" : "PHP 教程" }
{ "title" : "Java 教程" }
{ "title" : "MongoDB 教程" }
>
  • 注:skip(), limilt(), sort()三個放在一起執行的時候,執行的順序是先 sort(), 然后是 skip(),最后是顯示的 limit()
17、索引——createIndex()方法
>db.collection.createIndex(keys, options)
#key為需要創建索引字段,1 為指定按升序創建索引


舉例
>db.collection.createIndex({'title': 1})
#使用多個字段創建索引(關系型數據庫中稱作復合索引)
>db.collection.createIndex({'title': 1, 'description': -1})
18、聚合——aggregate()方法
>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
  • 集合

    {
       _id: ObjectId(7df78ad8902c)
       title: 'MongoDB Overview', 
       description: 'MongoDB is no sql database',
       by_user: 'runoob.com',
       url: 'http://www.runoob.com',
       tags: ['mongodb', 'database', 'NoSQL'],
       likes: 100
    },
    {
       _id: ObjectId(7df78ad8902d)
       title: 'NoSQL Overview', 
       description: 'No sql database is very fast',
       by_user: 'runoob.com',
       url: 'http://www.runoob.com',
       tags: ['mongodb', 'database', 'NoSQL'],
       likes: 10
    },
    {
       _id: ObjectId(7df78ad8902e)
       title: 'Neo4j Overview', 
       description: 'Neo4j is no sql database',
       by_user: 'Neo4j',
       url: 'http://www.neo4j.com',
       tags: ['neo4j', 'database', 'NoSQL'],
       likes: 750
    },
    
  • 舉例

    #計算每個作者所寫的文章數 
    >db.collection.aggregate([{$group: {_id: '$by_user', num_tutorial: {$sum: 1}}}])   
    {
       "result" : [
          {
             "_id" : "runoob.com",
             "num_tutorial" : 2
          },
          {
             "_id" : "Neo4j",
             "num_tutorial" : 1
          }
       ],
       "ok" : 1
    }
    >
    類似于
    select by_user, count(*) from collection group by by_user  
    
聚合表達式
  • 管道的概念


    聚合框架中常用的幾個操作

1、$project實例

  >db.mycol.aggregate(
        {$project:{
              title: 1,
              author: 1,
        }});

2、$match實例

#$match用于獲取分數大于70小于或等于90記錄,然后將符合條件的記錄送到下一階段$group管道操作符進行處理。
>db.mycol.aggregate([
                {$match: {score: {$gt: 70, $lte: 90}}} ,
                {$group: {_id: null, count: {$sum: 1}}}           
                ]);

3、skip實例

  >db.mycol.aggregate(
              {$skip: 5});
19、MongoDB關系:

1:1
1:N
N:1
N:N

  • 嵌入式關系

    {"_id":ObjectId("52ffc33cd85242f436000001"),
     "contact": "987654321",
     "dob": "01-01-1991",
     "name": "Tom Benzamin",
     "address": [
        {
           "building": "22 A, Indiana Apt",
           "pincode": 123456,
           "city": "Los Angeles",
           "state": "California"
        },
        {
           "building": "170 A, Acropolis Apt",
           "pincode": 456789,
           "city": "Chicago",
           "state": "Illinois"
        }]
    }
    
    
    #查詢用戶地址
    db.users.findOne({"name": "Tom Benzamin"}, {"address": 1})
    
  • 引用式關系

    #通過引用文檔的id字段來建立關系
    {
       "_id":ObjectId("52ffc33cd85242f436000001"),
       "contact": "987654321",
       "dob": "01-01-1991",
       "name": "Tom Benzamin",
       "address_ids": [
          ObjectId("52ffc4a5d85242602e000000"),
          ObjectId("52ffc4a5d85242602e000001")
       ]
    }
    
    
    #這種方法需要兩次查詢:
    #第一次查詢用戶地址的對象id;
    #第二次通過查詢的id獲取用戶的詳細地址信息。
    >var result = db.users.findOne({"name": "Tom Benzamin"}, {"address_ids": 1})
    >var addresses = db.address.find({"_id": {"$in": result["address_ids"]}})
    
20、數據庫引用:
  • 使用DBRefs

    {$ref:  , $id:  , $db:  }
    

ref:集合名稱id:引用的id
$db:數據庫名稱,可選參數

  { "_id":ObjectId("53402597d852426020000002"),
     "address": {
           "$ref": "address_home",
           "$id": ObjectId("534009e4d852427820000002"),
           "$db": "runoob"
            },
     "contact": "987654321",
     "dob": "01-01-1991",
     "name": "Tom Benzamin"
  }


  #通過指定$ref參數(address_home集合)來查找集合中指定id的用戶地址信息
  >var user = db.users.findOne({"name": "Tom Benzamin"})
  >var dbRef = user.address
  >db[dbRef.$ref].findOne({"_id": (dbRef.$id)})
  
  #返回結果
  {
     "_id" : ObjectId("534009e4d852427820000002"),
     "building" : "22 A, Indiana Apt",
     "pincode" : 123456,
     "city" : "Los Angeles",
     "state" : "California"
  }
21、查詢分析:
  • 使用explain()

    #在集合中創建索引
    >db.users.ensureIndex({gender: 1, user_name: 1})
    >db.users.find({gender: "M"}, {user_name: 1, _id: 0}).explain()
    
    
    #查詢結果
    {
       "cursor" : "BtreeCursor gender_1_user_name_1",
       "isMultiKey" : false,
       "n" : 1,
       "nscannedObjects" : 0,
       "nscanned" : 1,
       "nscannedObjectsAllPlans" : 0,
       "nscannedAllPlans" : 1,
       "scanAndOrder" : false,
       "indexOnly" : true,
       "nYields" : 0,
       "nChunkSkips" : 0,
       "millis" : 0,
       "indexBounds" : {
          "gender" : [
             [
                "M",
                "M"
             ]
          ],
          "user_name" : [
             [
                {
                   "$minElement" : 1
                },
                {
                   "$maxElement" : 1
                }
             ]
          ]
       }
    }
    

indexOnly: 字段為 true ,表示我們使用了索引。

cursor:因為這個查詢使用了索引,MongoDB 中索引存儲在B樹結構中,所以這是也使用了 BtreeCursor 類型的游標。如果沒有使用索引,游標的類型是 BasicCursor。這個鍵還會給出你所使用的索引的名稱,你通過這個名稱可以查看當前數據庫下的system.indexes集合(系統自動創建,由于存儲索引信息,這個稍微會提到)來得到索引的詳細信息。

n:當前查詢返回的文檔數量。

nscanned/nscannedObjects:表明當前這次查詢一共掃描了集合中多少個文檔,我們的目的是,讓這個數值和返回文檔的數量越接近越好。

millis:當前查詢所需時間,毫秒數。

indexBounds:當前查詢具體使用的索引。

  • 使用hint()
    使用hint來強制MongoDB使用一個指定的索引。

    #如下查詢實例指定了使用 gender 和 user_name 索引字段來查詢:
    >db.users.find({gender: "M"}, {user_name: 1, _id: 0}).hint({gender: 1, user_name: 1})
    #可以使用 explain() 函數來分析以上查詢:
    >db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1}).explain()
    
22、原子操作:

原子操作常用命令:

  • $set:用來指定一個鍵并更新鍵值,若鍵不存在則創建

    { $set : { field : value } }
    
  • $unset:用來刪除一個鍵。

    { $unset : { field : 1} }
    
  • $inc:可以對文檔的某個值為數字型(只能為滿足要求的數字)的鍵進行增減的操作。

    { $inc : { field : value } }
    
  • $push:把value追加到field里面去,field一定要是數組類型才行,如果field不存在,會新增一個數組類型加進去。

    { $push : { field : value } }
    
  • $pushAll:一次可以追加多個值到一個數組字段內。

    { $pushAll : { field : value_array } }
    
  • $pull:從數組field內刪除一個等于value值。

    { $pull : { field : _value } }
    
  • $addToSet:增加一個值到數組內,而且只有當這個值不在數組內才增加。

  • $pop:刪除數組的第一個或最后一個元素

    { $pop : { field : 1 } }
    
  • $rename:修改字段名稱

    { $rename : { old_field_name : new_field_name } }
    
  • $bit:位操作,integer類型

    {$bit : { field : {and : 5}}}
    

舉例

> t.find() 
{ "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 3 }, { "by" : "jane", "votes" : 7 } ] }

> t.update( {'comments.by':'joe'}, {$inc:{'comments.$.votes':1}}, false, true )

> t.find() 
{ "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 4 }, { "by" : "jane", "votes" : 7 } ] }
23、高級索引:
{
   "address": {
      "city": "Los Angeles",
      "state": "California",
      "pincode": "123"
   },
   "tags": [
      "music",
      "cricket",
      "blogs"
   ],
   "name": "Tom Benzamin"
}
  • 索引數組字段

    >db.users.ensureIndex({"tags": 1})
    #創建索引后,檢索集合的tags字段
    >db.users.find({tags: "music"})
    >db.users.find({tags: "music"}).explain()
    
  • 索引子文檔字段

    >db.users.ensureIndex({"address.city": 1, "address.state": 1, "address.pincode": 1})
    >db.users.find({"address.city": "Los Angeles"})
    >db.users.find({"address.state":"California","address.city":"Los Angeles"})
    >
    
24、ObjectId:
  • ObjectId格式:
    前4個字節表示時間戳
    接下來的3個字節是機器標識碼
    緊接的兩個字節由進程id組成(PID)
    最后三個字節是隨機數

    #創建新的ObjectId
    >newObjectId = ObjectId()
    ObjectId("5349b4ddd2781d08c09890f3")
    
    
    #創建文檔的時間戳
    >ObjectId("5349b4ddd2781d08c09890f4").getTimestamp()
    #返回文檔創建時間
    ISODate("2014-04-12T21:49:17Z")
    
    
    #ObjectId轉換為字符串
    >new ObjectId().str
    #返回Guid格式的字符串
    5349b4ddd2781d08c09890f3
    
25、Map Reduce:
  • MapReduce基本語法:

    >db.collection.mapReduce(
          function()  {emit(key, value);},   //map函數
          function(key, values) {return reduceFunction},   //reduce函數
          {
              out: collection,
              query: document,
              sort: document,
              limit: number
          }
    )
    

注:使用 MapReduce 要實現兩個函數 Map 函數和 Reduce 函數,Map 函數調用 emit(key, value),遍歷 collection 中所有的記錄,將 key 與 value 傳遞給 Reduce 函數進行處理。

  • 參數說明
    **map **:映射函數 (生成鍵值對序列,作為 reduce 函數參數)。
    reduce:統計函數,reduce函數的任務就是將key-values變成key-value,也就是把values數組變成一個單一的值value。。
    out:統計結果存放集合 (不指定則使用臨時集合,在客戶端斷開后自動刪除)。
    query:一個篩選條件,只有滿足條件的文檔才會調用map函數。(query,limit,sort可以隨意組合)
    sort:和limit結合的sort排序參數(也是在發往map函數前給文檔排序),可以優化分組機制
    limit:發往map函數的文檔數量的上限(要是沒有limit,單獨使用sort的用處不大)

  • 舉例
    在集合 orders 中查找 status:"A" 的數據,并根據 cust_id 來分組,并計算 amount 的總和。


    >db.posts.mapReduce( 
       function() { emit(this.user_name,1); }, 
       function(key, values) {return Array.sum(values)}, 
          {  
             query:{status:"active"},  
             out:"post_total" 
          }
    )
    
    #輸出結果
    {
            "result" : "post_total",
            "timeMillis" : 23,
            "counts" : {
                    "input" : 5,
                    "emit" : 5,
                    "reduce" : 1,
                    "output" : 2
            },
            "ok" : 1
    }
    

未完待續...

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容