比较/排序顺序

比较不同BSON类型的值时,MongoDB使用以下比较顺序,从最低到最高:

  1. MinKey(内部类型)
  2. 空值
  3. 数字(整数,整数,双精度数,小数)
  4. 符号,字符串
  5. 宾语
  6. 数组
  7. BinData
  8. 对象编号
  9. 布尔型
  10. 日期
  11. 时间戳记
  12. 正则表达式
  13. MaxKey(内部类型)

数值类型

为了进行比较,MongoDB将某些类型视为等效。例如,数字类型在比较之前先进行转换。

字符串

二进制比较

默认情况下,MongoDB使用简单的二进制比较来比较字符串。

整理

3.4版的新功能。

归类允许用户为字符串比较指定特定于语言的规则,例如字母大写和重音符号的规则。

整理规范具有以下语法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
   locale: <string>,
   caseLevel: <boolean>,
   caseFirst: <string>,
   strength: <int>,
   numericOrdering: <boolean>,
   alternate: <string>,
   maxVariable: <string>,
   backwards: <boolean>
}

指定排序规则时,该locale字段为必填字段;所有其他排序规则字段都是可选的。

如果没有为集合或操作指定排序规则,则MongoDB使用先前版本中使用的简单二进制比较进行字符串比较。

数组

对于数组,升序排序比较数组的最小元素,降序排序比较数组的最大元素。这样,当将值是单元素数组(例如[ 1 ])的字段与非数组字段(例如2)进行比较时,比较是1和2之间。空数组(例如[ ])的比较将空数组视为小于或缺少字段。

对象

MongoDB对BSON对象的比较使用以下顺序:

  1. 按照键值对在BSON对象中出现的顺序递归比较它们。
  2. 比较关键字段名称。
  3. 如果关键字段名称相等,则比较字段值。
  4. 如果字段值相等,则比较下一个键/值对(返回步骤1)。没有其他对的对象小于具有其他对的对象。

日期和时间戳

日期对象在时间戳对象之前。

不存在的字段

比较将不存在的字段视为空BSON对象。这样,对文档{}和{a:null}中的a字段进行排序将按排序顺序将文档视为等效。

BinData

MongoDB按BinData以下顺序排序:

  1. 首先,数据的长度或大小。
  2. 然后,按BSON的一字节子类型。
  3. 最后,通过数据执行逐字节比较。

$eq

指定相等条件。该$eq操作符匹配字段的值等于指定值的文档。

1
{ <field>: { $eq: <value> } }

该$eq表达式等效于。{ field: <value> }

特性

比较顺序

有关不同BSON类型值的比较,请参见指定的BSON比较顺序。

匹配一个文档

如果指定的<value>是文档,则文档中字段的顺序很重要。

匹配一个数组值

如果指定的<value>是数组,则MongoDB将<field>匹配与该数组完全匹配的文档,或者<field> 包含与该数组完全匹配的元素的文档。元素的顺序很重要。

例子

以下示例inventory使用以下文档查询集合:

1
2
3
4
5
{ _id: 1, item: { name: "ab", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] }
{ _id: 2, item: { name: "cd", code: "123" }, qty: 20, tags: [ "B" ] }
{ _id: 3, item: { name: "ij", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 4, item: { name: "xy", code: "456" }, qty: 30, tags: [ "B", "A" ] }
{ _id: 5, item: { name: "mn", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }

等于指定值

下面的示例查询inventory集合以选择qty字段值等于的所有文档20:

1
db.inventory.find( { qty: { $eq: 20 } } )

该查询等效于:

1
db.inventory.find( { qty: 20 } )

这两个查询都匹配以下文档:

1
2
{ _id: 2, item: { name: "cd", code: "123" }, qty: 20, tags: [ "B" ] }
{ _id: 5, item: { name: "mn", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }

嵌入式文档中的字段等于值

以下示例查询inventory集合以选择文档中name字段值item 等于的所有文档"ab"。要在嵌入式文档中的字段上指定条件,请使用点符号。

1
db.inventory.find( { "item.name": { $eq: "ab" } } )

该查询等效于:

1
db.inventory.find( { "item.name": "ab" } )

这两个查询都与以下文档匹配:

1
{ _id: 1, item: { name: "ab", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] }

数组元素等于一个值

以下示例查询inventory集合,以选择tags数组包含值"B"的元素的所有文档:

1
db.inventory.find( { tags: { $eq: "B" } } )

该查询等效于:

1
db.inventory.find( { tags: "B" } )

这两个查询都匹配以下文档:

1
2
3
4
{ _id: 1, item: { name: "ab", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] }
{ _id: 2, item: { name: "cd", code: "123" }, qty: 20, tags: [ "B" ] }
{ _id: 3, item: { name: "ij", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 4, item: { name: "xy", code: "456" }, qty: 30, tags: [ "B", "A" ] }

等于一个数组值

以下示例查询inventory集合,以选择该tags数组与指定数组完全相等或该tags数组包含等于该数组的元素的所有文档。

1
db.inventory.find( { tags: { $eq: [ "A", "B" ] } } )

该查询等效于:

1
db.inventory.find( { tags: [ "A", "B" ] } )

这两个查询都匹配以下文档:

1
2
{ _id: 3, item: { name: "ij", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 5, item: { name: "mn", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }

$gt

语法:{field: {$gt: value} }

$gt选择的值field大于(即>)指定的那些文档 value。

对于大多数数据类型,比较运算符仅对BSON类型与查询值的类型匹配的字段执行比较 。MongoDB通过Type Bracketing支持有限的跨BSON比较。

考虑以下示例:

1
db.inventory.find( { qty: { $gt: 20 } } )

此查询将选择inventory集合中qty字段值大于20的所有文档。

考虑以下示例,该示例将$gt 运算符与嵌入式文档中的字段一起使用:

1
db.inventory.update( { "carrier.fee": { $gt: 2 } }, { $set: { price: 9.99 } } )

此update()操作将找到的第一个文档中包含嵌入式文档carrier的fee字段的值大于2的值设置price。

要price在包含嵌入文档的carrier的fee字段值大于2的所有文档中设置该字段的值,请在update()方法中指定选项multi:true

1
2
3
4
5
db.inventory.update(
   { "carrier.fee": { $gt: 2 } },
   { $set: { price: 9.99 } },
   { multi: true }
)

$gte

语法:{field: {$gte: value} }

$gte选择的值field大于或等于(即>=)指定值(例如value)的文档 。

对于大多数数据类型,比较运算符仅对BSON类型与查询值的类型匹配的字段执行比较 。MongoDB通过Type Bracketing支持有限的跨BSON比较。

考虑以下示例:

1
db.inventory.find( { qty: { $gte: 20 } } )

此查询将选择的所有文件inventory,其中qty字段的值大于或等于20。

考虑以下示例,该示例将$gte 运算符与嵌入式文档中的字段一起使用:

1
db.inventory.update( { "carrier.fee": { $gte: 2 } }, { $set: { price: 9.99 } } )

此update()操作将设置price包含嵌入文档carrier的fee字段的值,该嵌入文档的字段值大于或等于2。

$in

在$in选择其中一个场的值等于指定数组中的任何值的文件。要指定 $in表达式,请使用以下原型:

有关不同BSON类型值的比较,请参见指定的BSON比较顺序。

1
{ field: { $in: [<value1>, <value2>, ... <valueN> ] } }

如果该字段包含一个数组,则$in运算符将选择其字段包含一个数组的文档,该数组包含至少一个与指定数组中的值匹配的元素(例如<value1><value2>等)

例子

使用$in运算符来匹配值

考虑以下示例:

1
db.inventory.find( { qty: { $in: [ 5, 15 ] } } )

该查询选择inventory集合中qty字段值为5或的15所有文档。尽管可以使用$or运算符表示此查询 ,但是在同一字段上执行相等性检查时,请选择$in运算符而不是$or运算符。

使用$in运算符匹配数组中的值

集合inventory包含包含字段的文档, tags如下所示:

1
{ _id: 1, item: "abc", qty: 10, tags: [ "school", "clothing" ], sale: false }

然后,下面的update()操作将设定的sale字段值true,其中tags字段保持与至少一个元素匹配"appliances"或"school"。

1
2
3
4
db.inventory.update(
                     { tags: { $in: ["appliances", "school"] } },
                     { $set: { sale:true } }
                   )

将$in运算符与正则表达式一起使用

$in可利用常规的正则表达式匹配指定值/pattern/。您不能使用$regex 运算符表达式$in

考虑以下示例:

1
db.inventory.find( { tags: { $in: [ /^be/, /^st/ ] } } )

此查询选择inventory集合中的所有文档,其中该tags字段包含以be或st开头的字符串,或包含至少一个以be或st开头的元素的数组。

$lt

语法:{field: {$lt: value} }

$lt选择的值field小于(即<)指定的文档 value。

对于大多数数据类型,比较运算符仅对BSON类型与查询值的类型匹配的字段执行比较 。MongoDB通过Type Bracketing支持有限的跨BSON比较。

考虑以下示例:

1
db.inventory.find( { qty: { $lt: 20 } } )

此查询将选择inventory集合中qty字段值小于20的所有文档。

考虑以下示例,该示例将$lt运算符与嵌入式文档中的字段一起使用:

1
db.inventory.update( { "carrier.fee": { $lt: 20 } }, { $set: { price: 9.99 } } )

此update()操作将price在包含嵌入文档的文档中设置字段值,该嵌入文档carrier的fee字段值小于20。

$lte

语法:{ field: { $lte: value} }

$lte选择的值field小于或等于<=指定 的文档 value。

对于大多数数据类型,比较运算符仅对BSON类型与查询值的类型匹配的字段执行比较 。MongoDB通过Type Bracketing支持有限的跨BSON比较。

考虑以下示例:

1
db.inventory.find( { qty: { $lte: 20 } } )

此查询将选择inventory集合中qty字段值小于或等于20的所有文档。

考虑以下示例,该示例将$lt 运算符与嵌入式文档中的字段一起使用:

1
db.inventory.update( { "carrier.fee": { $lte: 5 } }, { $set: { price: 9.99 } } )

此update()操作将price在包含嵌入式文档的文档中设置字段值,该嵌入式文档carrier的fee字段值小于或等于5。

$ne

语法:{field: {$ne: value} }

$ne选择的值field不等于指定的文档 value。这包括不包含的文档field。

有关不同BSON类型值的比较,请参见指定的BSON比较顺序。

考虑以下示例:

1
db.inventory.find( { qty: { $ne: 20 } } )

此查询将选择inventory集合中qty字段值不相等的所有文档20,包括不包含该qty字段的那些文档。

考虑以下示例,该示例$ne 在嵌入式文档中使用运算符和字段:

1
db.inventory.update( { "carrier.state": { $ne: "NY" } }, { $set: { qty: 20 } } )

此update()操作将qty在包含嵌入式文档的文档中设置字段值,该嵌入式文档carrier的state字段值不等于“NY”,或者该state字段或carrier嵌入式文档不存在。

不等式操作者$ne是非常没有选择性的,因为它往往是指数的很大一部分相匹配。在许多情况下,$ne带有索引的查询的性能可能不比$ne必须扫描集合中所有文档的查询更好。

$nin

语法:{ field: { $nin: [ <value1>, <value2> ... <valueN> ]} }

$nin 选择以下文档:

  • 该field值不在指定的范围内array 或
  • 在field不存在。

有关不同BSON类型值的比较,请参见指定的BSON比较顺序。

考虑以下查询:

1
db.inventory.find( { qty: { $nin: [ 5, 15 ] } } )

此查询将选择的所有文件inventory,其中收集qty字段值确实不等于5也不等于15。所选文档将包括那些不包含该qty字段的文档 。

如果该字段包含一个数组,则$nin运算符将选择其字段包含一个数组且其元素不等于指定数组中的值的文档(例如<value1><value2>等)。

考虑以下查询:

1
db.inventory.update( { tags: { $nin: [ "appliances", "school" ] } }, { $set: { sale: false } } )

update()操作将在集合中设置sale字段的值,其中tags字段包含一个数组,该数组没有与数组[“ appliances”,“ school”]中的元素匹配的元素,或者文档不包含tags字段。

不等式操作者$nin是非常没有选择性的,因为它往往是指数的很大一部分相匹配。结果,在许多情况下,$nin带有索引的查询的性能可能不比$nin必须扫描集合中所有文档的查询更好。