MongoDB(operator)

关于operators

官方参考文档:https://docs.mongodb.org/manual/reference/
下面会对这些operator进行详解,先参考如下分类:

Query and Projection Operators

  • Comparison Query Operators 例如:$eq $gt $gte $lt $lte $ne $in $nin
  • Logical Query Operators 例如:$or $and $not $nor
  • Element Query Operators 例如:$exist $type
  • Evaluation Query Operators 例如:$mod $regex $text $where
  • Geospatial Query Operators
  • Query Operator Array 例如:$all $elemMatch(query) $size
  • Bitwise Query Operators 例如:$bitsAllSet $bitsAnySet $bitsAllClear $bitsAnyClear
  • Projection Operators 例如:$(projection) $elemMatch(projection) $meta $slice(projection)

Update Operators

  • Field Update Operators 例如:$inc $mul $rename $setOnInsert $set $unset $min $max $currentDate
  • Array Update Operators 例如:$(update) $addToSet $pop $pullAll $pull $pushAll $push $each $slice $sort $position
  • Bitwise Update Operators 例如:$bit
  • Isolation Update Operators 例如:$isolated

Aggregation Pipeline Operators

  • Pipeline Aggregation Stages 例如:$project $match $redact $limit $skip $unwind $group $sample $sort $geoNear $lookup $out $indexStats
  • Boolean Aggregation Operators
  • Set Operators (Aggregation)
  • Comparison Aggregation Operators
  • Arithmetic Aggregation Operators
  • String Aggregation Operators
  • Text Search Aggregation Operators
  • Array Aggregation Operators
  • Aggregation Variable Operators
  • Aggregation Literal Operators
  • Date Aggregation Operators
  • Conditional Aggregation Operators
  • Group Accumulator Operators

Operators详细解释如下:

Query and Projection Operators

  • Comparison Query Operators

    • $ne
      功能:用于比较,意义是not equal to,一般用于find或update。
      用法:{field: {$ne: value}}
      例子:db.test.find({ "age": {$ne: 20} })
      例子效果:列出test集合中所有age不等于20的文档
      注:如果field是个数组type,那么value可以是数组中的一个元素,也可以是数组。
      
    • $lt
      功能:用于比较,意义是less than,一般用于find或update。
      用法: {field: {$lt: value} }
      例子:db.test.find( { "number": { $lt: 20 } } )
      例子效果:列出test集合中所有number<20的文档
      注:比较操作符可以搭配组合实习区间筛选。
      
    • $gt
      功能:用于比较,意义是greater than,一般用于find或update。
      用法:{field: {$gt: value} }
      例子:db.test.find( { "age": { $gt: 20 } } )
      例子效果:列出test集合中所有age>20的文档
      注:比较操作符可以搭配组合实习区间筛选。
      
    • $lte
      功能:用于比较,意义是less than or equal to,一般用于find或update。
      用法:{ field: { $lte: value} }
      例子:db.test.find( { "number": { $lte: 20 } } )
      例子效果:列出test集合中所有number<=20的文档
      注:比较操作符可以搭配组合实习区间筛选。
      
    • $gte
      功能:用于比较,意义是greater than or equal to,一般用于find或update。
      用法:{field: {$gte: value} }
      例子:db.test.find( { "age": { $gte: 20 } } )
      例子效果:列出test集合中所有age>=20的文档
      注:比较操作符可以搭配组合实习区间筛选。用于Date格式尤为合适。
      
    • $eq
      功能:用于匹配,意义是equal to,一般用于find或update。
      用法:{ <field>: { $eq: <value> } }
      例子:db.test.find( { "age": { $eq: 10086 } } )
      例子效果:精确匹配,等同于db.test.find( { "age": 10086 } )
      注:一般不用,可以简写。比较操作符可以搭配组合实习区间筛选。
      
    • $in
      功能:用于匹配,一般用于find或update,匹配一个数组中的任一个。
      用法:{ field: { $in: [<value1>, <value2>, ... <valueN> ] } }
      例子:db.students.find( { "age": { $in: [ 14, 15 ] } } )
      例子效果:列出所有14、15岁的学生。
      注:别看错了,这个数组不是区间,并不等同于$gte搭配$ltq。
      
    • $in
      功能:用于匹配,一般用于find或update,筛出不匹配完全不匹配的文档。
      用法:{ field: { $nin: [ <value1>, <value2> ... <valueN> ]} }
      例子:db.students.find( { "age": { $in: [ 17, 18, 19 ] } } )
      例子效果:列出所有非17、18岁、19岁的学生,不允许他们参加高考。
      注:
      
  • Logical Query Operators

    • $or
      功能:逻辑或,用于匹配,只要有一个field匹配中的就满足条件,一般用于find或update。
      用法:{ $or: [ { <expression1> }, { <expression2> }, ...  } ] }
      例子:db.goods.find( { $or: [ { quality: { $gt: 20 } }, { price: 10 } ] } )
      例子效果:挑出那些要么质量好的,要么价格便宜的商品。
      注:每个expression的限制程度应该升序,这样余下的筛选工作才会更快。
      
    • $and
      功能:逻辑与,用于匹配,选中所有field都匹配的文档,一般用于find或update。
      用法:{ $and: [ { <expression1> }, { <expression2> } , ...  } ] }
      例子:db.goods.find( { $and: [ { price: 2.0 }, { city: "Beijing" } ] } )
      例子效果:列出要在北京能够以2块钱买得到的东西。
      注:每个expression的限制程度应该降序,这样大部分就已经被忽略了。
      
    • $not
      功能:逻辑反,用于匹配,搜到那些不匹配的文档,一般用于find或update。
      用法:{ field: { $not: { <operator-expression> } } }
      例子:db.test.find( { price: { $not: { $gt: 1.99 } } } )
      例子效果:$not和$gt搭配,相当于<=号。价格在1.99以上的被选中。
      注:不能与$regex搭配使用,而是用/xxx/来使用正则,如find( { item: { $not: /^p.*/ } } )。
      
    • $nor
      功能:选中那些全部expression都不匹配的文档。
      用法:{ $nor: [ { <expression1> }, { <expression2> }, ...  ] }
      例子:db.people.find( { $nor: [ { body: "fat" }, { hair: "black" } ] } )
      例子效果:选一些古惑仔去打架,黑头发和太胖的就不行啦。
      注:只要文档匹配到任意一个,都不会被选中。
      
  • Element Query Operators

    • $exist
      功能:过滤掉指定field是存在or不存在的文档。
      用法:{ field: { $exists: <boolean> } }
      例子:db.inventory.find( { "num": { $exists: true } } )
      例子效果:只查询具有num域的文档,包括该域为null的文档。
      注:true为必须存在字段,false在必须不存在。
      
    • $type
      功能:类型匹配,查询时可指定搜索域的类型,可避免乱七八糟的类型。
      用法:{ field: { $type: <BSON type number> | <String alias> } }
      例子1:db.addressBook.find( { "zipCode" : { $type : 1 } } )
      例子2:db.addressBook.find( { "zipCode" : { $type : "double" } } )
      例子效果:都是只考虑那些zipCode类型为double的文档。
      注:关于array类型有些注意点。number类型可以通指。
      
  • Evaluation Query Operators

    • $mod
      功能:取模操作,并指定取模结果来返回文档,一般用于find。
      用法:{ field: { $mod: [ divisor, remainder ] } }
      例子:db.test.find( { number: { $mod: [ 4, 0 ] } } )
      例子效果:选中number域中的值除以4余0的文档。
      注:
      
    • $regex
      功能:使用正则表达式进行匹配,3种使用方式有各自的限制。
      用法1:{ <field>: { $regex: /pattern/, $options: '<options>' } }
      用法2:{ <field>: { $regex: 'pattern', $options: '<options>' } }
      用法3:{ <field>: { $regex: /pattern/<options> } }
      例子:
      例子效果:
      注:<options>的参数很多,比如 i m x s 。
      
    • $text
      功能:指定要匹配的是字符串,提供匹配的高级操作。
      用法:
      { 
        $text: { 
          $search: <string>, 
          $language: <string>, 
          $caseSensitive: <boolean>, 
          $diacriticSensitive: <boolean> 
        }
      }
      注:字符串匹配操作比较复杂,参考官网。
      
    • $where
      功能:指定同个文档内的两个field进行比较,以进行特殊的筛选。
      用法1:db.myCollection.find( { $where: "this.credits == this.debits" } )  省略function写法。
      用法2:db.myCollection.find( { $where: function() { return (this.credits == this.debits) } }   
      用法3:db.myCollection.find( "this.credits == this.debits || this.credits > this.debits" )  当筛选条件仅有一个$where表达式时。
      用法4:db.myCollection.find( function() { return (this.credits == this.debits || this.credits > this.debits ) } )  当筛选条件仅有一个$where表达式时。
      注:若返回true则选中该文档。
      
  • Geospatial Query Operators

    • 二维相关的查询,暂时略。
  • Query Operator Array

    • $all
      功能:用于数组匹配,可以指定数组中必须包含的元素。
      用法:{ <field>: { $all: [ <value1> , <value2> ... ] } }
      例子:{ "money": { $all: [ 5 , 2 , 1 ] } }
      例子效果:想找10块钱零钱,找同时有散钱1、2、5的人。
      注:指定的value并没有先后顺序,只检测包含性,所以有多个也没有关系。
      
    • $elemMatch(query)
      功能:匹配内嵌文档或数组中的部分field。
      用法:{ <field>: { $elemMatch: { <query1>, <query2>, ... } } }
      例子:db.scores.find( { results: { $elemMatch: { $gte: 80, $lt: 85 } } })
      例子效果:对于那些results数组中具有区间[80,85)元素的文档选中。
      注:
      
    • $size
      功能:指定数组的大小。
      用法:db.collection.find( { <field>: { $size: <n> } } );
      例子:db.people.find( { "card": { $size: 5 } } );
      例子效果:集齐全5张卡片才能兑换礼品。
      注:不能与$gt等比较操作符搭配。具体见官网。
      
  • Bitwise Query Operators
  • Projection Operators
    • $(projection)
      功能:对array取下标。
      用法:db.collection.find( { <array.field>: <value> ...}, { "<array>.$": 1 } )
      例子:db.students.find( { grades: { $gte: 85 } }, { "grades.$": 1 } )
      例子效果:将选中文档中首个大于等于85的数返回。
      注:不能暴力使用多个array,提倡用$eleMatch。
      
    • $elemMatch(projection)
      功能:用于数组中的元素匹配,可用于find的第2个参数。
      用法:
      例子:db.schools.find( { zipcode: "63109" }, { students: { $elemMatch: { school: 102, age: { $gt: 10} } } } )
      例子效果:第2个参数是决定要返回的field的。
      注:看官网吧。
      
    • $meta
      功能:取出$text匹配的文档分数,看text了解score的概念就懂了。
      用法:{ $meta: <metaDataKeyword> }
      例子:db.collection.find( {$text: { $search: "coffee bake" } }, { score: { $meta: "textScore" } })
      例子效果:cofee bake两个单词的匹配工作会使得每个文档得到一个分数,$meta调出这个分数。
      注:要配合$text来使用,仅用于字符串搜索。
      
    • $slice(projection)
      功能:在查询中将数组进行切片。
      用法:{ <array>: {$slice: <count-expression> } }
      例子:db.posts.find( {_id:1}, { comments: { $slice: [23, 5] } } )
      例子效果:显示id=1的整个文档,但其中comments数组仅显示从第24开始的5个元素。
      注:<count-expression>有多种方式:<n>表前n个、<-n>表后n个、<[begin, n]>从下标begin开始的n个、<[-begin, n]>忽略掉后begin个再取后n个。
      

Update Operators

一个field可以有多个查询条件限制,但不能够对应多个修改器。如下都是修改器。

  • Field Update Operators

    • $inc
      功能:将文档中的某个field对应的value自增/减某个数字amount,是原子操作。
      用法:{ $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }
      例子:db.products.update( { _id: 1 }, { $inc: { quantity: -2} })
      例子效果:将id=1的文档的quanty项自减2。
      注:只允许操作数字型field(如浮点,整型),否则报错。若不存在field,则创建并初始化为0后再操作。
      
    • $mul
      功能:将文档内的指定域作乘法,是原子操作。
      用法:{ $mul: { field: <number> } }
      例子:db.products.update( { _id: 1 }, { $mul: { price: 1.25 } })
      例子效果:将_id=1的文档中的price域的值乘以1.25。
      注:若没有指定的field,将创建一个再赋值为0值。会涉及数值类型转化。
      
    • $rename
      功能:更改已存在的文档的指定field名称。
      用法:{$rename: { <field1>: <newName1>, <field2>: <newName2>, ... } }
      例子:db.students.update( { _id: 1 }, { $rename: { 'cell': 'mobile' } } )
      例子效果:将cell域名改成了mobile。
      注:其实使用了$unset和$set。
      
    • $setOnInsert
      功能:配合upsert操作,在作为insert时可以为新文档扩展更多的field。
      用法:db.collection.update( <query>, { $setOnInsert: { <field1>: <value1>, ... } }, { upsert: true })
      例子:db.products.update( { _id: 1 }, { $set: { item: "apple" }, $setOnInsert: { money: 100 } }, { upsert: true })
      例子效果:若_id=1的文档存在,仅改item,否则插入由item域和$setOnInsert所指定的域组成的文档。
      注:
      
    • $set
      功能:文档中value的替换,一般用于update。
      用法:{ $set: { <field1>: <value1>, ... } }
      例子:db.stuff.update( { _id: 100 }, { $set: { "job": "worker"} })
      例子效果:将id=100的文档的"job"项修改为worker。
      注:若field不存在,则创建。若field中包含dot,则会创建一个内嵌文档再填充。
      
    • $unset
      功能:删除文档中的某个项,同样可删内嵌型。
      用法:{ $unset: { <field1>: "", ... } }
      例子:db.products.update( { _id: 1 }, { $unset: { quantity: "", instock: "" } })
      例子效果:删除掉了id=1的文档的两个key。
      注:若文档中不存在field项,则不操作。
      
    • $min
      功能:更新一个field要么为指定的值,要么是不变,取决于其中的小者。
      用法:{ $min: { <field1>: <value1>, ... } }
      例子:db.scores.update( { _id: 1 }, { $min: { lowScore: 150 } } )
      例子效果:假设_id=1的文档中的lowScore的值为200,那么它立刻被更新为150。
      注:保证指定field的值小于等于我指定的值。
      
    • $max
      功能:与$min相反。
      注:
      
    • $currentDate
      功能: 设置指定field值为当前的时间。
      用法:{ $currentDate: { <field1>: <typeSpecification1>, ... } }
      例子:db.users.update( { _id: 1 }, { $currentDate: { "lastLogin": { $type: "timestamp" } } })
      例子效果:直接修改了lastLogin为当前时间戳。
      注:日期可以是Date()也可以是timestamp。
      
  • Array Update Operators

    • $(update)
      功能:定位符'$',可获取元素在array中的下标(从0开始),一般用于update。
      用法:{ "<array>.$" : value }
      例子:db.students.update( { _id: 1, grades: 80 }, { $set: { "grades.$" : 82 } })
      例子效果:将id=1的文档中的grades数组中的元素80搜出来,获取其在数组中的下标,以此为索引来更新元素为82。
      注:使用在其他地方有诸多限制,参考官方文档。
      
    • $addToSet
      功能:用于更新,添加一个value到一个array中,一般用于update第2个参数。
      用法:{ $addToSet: {<field1>: <value1>, ...} }
      例子:db.test.update( { "age":  20}, {$addToSet: { "email": "new@qq.com" }} )
      例子效果:将新邮箱插入到test集合中的所有age=20的文档中的email数组中的末尾。
      注:field只可以是array类型。在update时,若field不存在,则创建,若value已存在,则不操作。
         需要注意的是同时插入多个value于同一array的情况,要么每次都写field域,要么使用$each。
      
    • $pop
      功能:删除array的首元素或尾元素,一般用于update。
      用法:{ $pop: { <field>: <-1 | 1>, ... } }
      例子:db.students.update( { _id: 1 }, { $pop: { scores: -1 } } )
      例子效果:删除id=1的文档中scores数组的首元素。
      注:-1和1分别表示首、尾的意思。
      
    • $pullAll
      功能:pull的加强版,可以一次性保证多个元素不在数组中。
      用法:{ $pullAll: { <field1>: [ <value1>, <value2> ... ], ... } }
      例子:db.survey.update( { _id: 1 }, { $pullAll: { scores: [ 0, 5 ] } } )
      例子效果:保证了指定文档中scores数组不包含0和5。
      注:可以充当pull使用,也可以搭配使用。
      
    • $pull
      功能:删除满足条件的数组元素。
      用法:{ $pull: { <field1>: <value|condition>, <field2>: <value|condition>, ... } }
      例子:db.stores.update( { }, { $pull: {vegetables: "carrots" } })
      例子效果:保证stores集合中所有文档中的vegetables数组不含单词"carrots"。
      注:所有条件都匹配中了就删除。而欲删除array中的集合,则需指定完全匹配的集合。condition可以指定条件。
      
    • $pushAll
      功能:$push的加强版,可往一个数字中塞更多的元素。
      用法:{ $pushAll: { <field>: [ <value1>, <value2>, ... ] } }
      例子:同$pullAll
      注:指定单个value时就变成push了。
      
    • $push
      功能:往array中暴力添加元素,用于update。
      用法:{ $push: { <field1>: <value1>, ... } }
      例子:db.students.update( { _id: 1 }, { $push: { scores: 89 } })
      例子效果:在students集合中的id=1的文档中的scores数组中添加数字89。
      注:如果不存在field,则创建。可以搭配 $each $sort $slice 等等来使用。注意大量push时的效率。
      
    • $each
      功能:保证数组中必定存在某些元素,搭配$addToSet或$push使用。
      用法1:{ $addToSet: { <array>: { $each: [ <value1>, <value2> ... ] } } }
      例子1:db.test.update( { _id: 2 }, { $addToSet: { tags: { $each: [ "camera", "electronics", "accessories" ] } } } )
      例子1效果:在test集合中的id=2的文档的key=tags的value中添加3个单词。
      用法2:{ $push: { <array>: { $each: [ <value1>, <value2> ... ] } } }
      例子2:db.students.update( { name: "joe" }, { $push: { scores: { $each: [ 90, 92, 85 ] } } })
      例子2效果:在students集合中的name="joe"的所有文档都添加3个数字进scores数组。
      注:若存在,则不插入,否则插入进数组。
      
    • $slice
      功能:配合$each在$push之后,对扩充的数组进行切片。
      用法:{ $push: { <field>: { $each: [ <value1>, <value2>, ... ], $slice: <num> } }}
      例子:db.students.update( { _id: 1 }, { $push: { scores: { $each: [ 80, 78, 86 ], $slice: -5 } } })
      例子效果:往scores插入了3个数字后,只留下数组中的后5个元素,其他删除。
      注:作用比较特殊,可以用来保证数组中至少有多少个元素?
      
    • $sort
      功能:配合$each在$push中使用,在push一些元素进数组之后可以对数组进行排序。
      用法:{ $push: { <field>: { $each: [ <value1>, <value2>, ... ], $sort: <sort specification> } }}
      例子:db.students.update( { _id: 1 }, { $push: { quizzes: { $each: [ { id: 3, score: 8 }, { id: 4, score: 7 }, { id: 5, score: 6 } ], $sort: { score: 1 } } } })
      例子效果:数组中插入了3个文档,再按照score进行排序。
      注:作为push的修改器。
      
    • $position
      功能:配合$each在$push中使用,指定push一些元素到数组中的位置。
      用法:{ $push: { <field>: { $each: [ <value1>, <value2>, ... ], $position: <num> } }}
      例子:db.students.update( { _id: 1 }, { $push: { scores: { $each: [ 50, 60, 70 ], $position: 0 } } })
      例子效果:往数组scores的最前端插入3个元素。
      注:
      
  • Bitwise Update Operators

    • $bit
      功能:
      用法:{ $bit: { <field>: { <and|or|xor>: <int> } } }
      例子:db.switches.update( { _id: 1 }, { $bit: { expdata: { and: NumberInt(10) } } })
      例子效果:对expdata域的值作按位与操作。
      注:操作数只能是32位或64位整数。而mongo shell中的数字都是double型的,注意转。
      
  • Isolation Update Operators

    • $isolated
      功能:对多文档的write操作保持一致性,杜绝无处理一半的情况出现。
      用法:{ <query> , $isolated : 1 }
      例子:db.foo.update( { status : "A" , $isolated : 1 }, { $inc : { count : 1 } }, { multi: true })
      例子效果:修改多个选中的文档,在修改完成之前其他的client看不到任何变化。
      注:不能用于shard cluster。会使得WiredTiger变成单线程,影响并发性。不提供all-or-nothing。
      

Aggregation Pipeline Operators

  • Pipeline Aggregation Stages
    • $project

      功能:
      用法:{ $project: { <specifications> } }
      例子:
      例子效果:
      注:id域是默认输出的,指定不存在的field会被忽略。
      
    • $match $redact $limit $skip $unwind $group $sample $sort $geoNear $lookup $out $indexStats 这些还未整理。


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容