标签:city tree 实现 创建 方法 float RoCE 限制 --
示例文档:records
{
"_id": ObjectId("570c04a4ad233577f97dc459"),
"score": 1034,
"location": { state: "NY", city: "New York" }
}
索引规范中字段的值描述了该字段的索引种类。例如,值1指定按升序对项目进行排序的索引。值-1指定按降序排列项目的索引。
db.records.createIndex( { score: 1 } )
查询实例:
db.records.find( { score: 2 } )
db.records.find( { score: { $gt: 10 } } )
您可以在嵌入式文档中的字段上创建索引,就像您可以对文档中的顶级字段进行索引一样。嵌入字段上的索引与嵌入文档上的索引不同,后者包括完整的内容,直到索引中嵌入文档的最大索引大小。相反,嵌入字段上的索引允许您使用“点符号”来对嵌入文档进行内省。
db.records.createIndex( { "location.state": 1 } )
查询实例:
db.records.find( { "location.state": "CA" } )
db.records.find( { "location.city": "Albany", "location.state": "NY" } )
您还可以对嵌入的文档整体创建索引。
Location 字段是一个嵌入式文档,包含嵌入字段 city 和 state。下面的命令在 location 字段上创建一个索引作为一个整体:
db.records.createIndex( { location: 1 } )
查询示例:
db.records.find( { location: { state: “NY”, city: "New York" } } )
尽管查询可以使用索引,但结果集不包括上面的示例文档。当对嵌入的文档执行相等匹配时,字段顺序问题和嵌入的文档必须完全匹配。有关对嵌入文档进行查询的更多信息,请参见查询嵌入文档。
复合索引可以支持匹配多个字段的查询。
db.collection.createIndex( { <field1>: <type>, <field2>: <type2>, ... } )
索引规范中字段的值描述了该字段的索引种类。例如,值1指定按升序对项目进行排序的索引。值-1指定按降序排列项目的索引。
不能创建具有hashed索引类型的复合索引。
示例文档:products
{
"_id": ObjectId(...),
"item": "Banana",
"category": ["food", "produce", "grocery"],
"location": "4th Street Store",
"stock": 4,
"type": "cases"
}
db.products.createIndex( { "item": 1, "stock": 1 } )
复合索引中列出的字段的顺序很重要。索引将包含对文档的引用,这些文档首先根据项字段的值进行排序,然后在项字段的每个值中,根据 stock 字段的值进行排序。
db.products.find( { "item": "Banana", "stock": 4 } )
db.products.find( { "stock": 4,"item": "Banana" } )
使用时建议查询条件跟索引的顺序保持一致。
db.products.find( { "item": "Banana" } ) #使用索引
db.products.find( { "stock": 4 } ) #不使用索引
参考:https://blog.csdn.net/rcjjian/article/details/81532043
索引按升序(1)或降序(- 1)排序顺序存储对字段的引用。对于单字段索引,键的排序顺序并不重要,因为 MongoDB 可以沿任一方向遍历索引。但是,对于复合索引,排序顺序可以决定索引是否支持排序操作。
考虑一个包含用户名和日期字段的文档的集合事件。应用程序可以发出查询,返回按升序的用户名值排序的结果,然后按降序(即最近到最后一次)的日期值排序的结果,例如:
db.events.find().sort( { username: 1, date: -1 } )
或者查询返回的结果首先按照用户名值降序排序,然后按照日期值升序排序,例如:
db.events.find().sort( { username: -1, date: 1 } )
下面的索引可以支持这两种排序操作:
db.events.createIndex( { "username" : 1, "date" : -1 } )
或者
db.events.createIndex( { "username" : -1, "date" : 1 } )
但是,上面的索引不支持通过升序用户名值和升序日期值进行排序,例如:
db.events.find().sort( { username: 1, date: 1 } )
也不支持按照用户名字段降序和按照日期字段降序的排序条件:
db.events.find().sort( { username: -1, date: -1 } )
要想支持上面的两种排序必须新建一个复合索引:
db.events.createIndex( { "username" : 1, "date" : 1 } )
或者
db.events.createIndex( { "username" : -1, "date" : -1 } )
总结:查询的条件与创建索引的字段排序一致或者两个字段取反后一致时可使用该索引。
示例文档:products
{
"_id": ObjectId(...),
"item": "Banana",
"category": ["food", "produce", "grocery"],
"location": "4th Street Store",
"stock": 4,
"type": "cases"
}
索引前缀是索引字段的开始子集。例如,考虑下面的复合索引:
{ "item": 1, "location": 1, "stock": 1 }
索引有以下索引前缀:
{ "item": 1}
{ "item": 1, "location": 1 }
对于复合索引,MongoDB 可以使用索引来支持对索引前缀的查询。因此,MongoDB 可以使用索引查询以下字段:
MongoDB 还可以使用索引来支持对 item 和 stock 字段的查询,因为 item 字段对应于一个前缀。但是,在这种情况下,索引在支持查询方面的效率将不如索引仅针对item和stock时的效率。索引字段按顺序进行解析; 如果查询省略了特定的索引前缀,则无法使用该前缀之后的任何索引字段。
由于对 item 和 stock 的查询省略了 location index 前缀,因此不能使用 location 后面的 stock index 字段。只有索引中的item字段可以支持此查询。
这两段话的意思是 执行 db.products.find({ "item": "Banana", "stock": 4 }) 查询时 只有item字段用到了索引,字段stock没有使用索引。
MongoDB 不能使用索引来支持包含以下字段的查询,因为没有item字段,所列出的字段都不对应前缀索引:
如果您有一个集合,其前缀既有复合索引又有索引(例如{ a: 1,b: 1}和{ a: 1}) ,如果这两个索引都没有稀疏或唯一的约束,那么您可以删除前缀(例如{ a: 1})上的索引。MongoDB 将在所有使用前缀索引的情况下使用复合索引。
即{ a: 1,b: 1}和{ a: 1} 会使用{ a: 1,b: 1} 索引{ a: 1} 将不被使用
稀疏索引:稀疏索引(或者称间隙索引)就是只包含有索引字段的文档的条目,即使索引字段包含一个空值。也就是说间隙索引可以跳过那些索引键不存在的文档。因为他并非包含所有的文档,因此称为稀疏索引。与之相对的非稀疏索引或者说普通索引则包含所有的文档以及为那些不包含索引的字段存储null值。
如果要索引数组类型的字段,MongoDB可以在数组每个元素上创建索引。这种多键索引可以有效的支持数组元素查询。多键索引建立在具体的值(比如字符串、数字)或内嵌文档的数组上。
创建多键索引的语法:db.collection.createIndex()
db.coll.createIndex({<field>:<1 or -1>})
MongoDB会自动在数组字段上面创建多键索引,不需要我们做特别的声明
索引扫描的范围定义了在查询期间要检索的部分索引。当作一个索引有多个谓词(predicates)作用于它时,MongoDB将尝试通过相交或复合来组合这些谓词的边界,以产生具有较小扫描范围。
看看sql server关于谓词(predicates)的解释:
什么是谓词呢?谓词是取值为 TRUE、FALSE 或 UNKNOWN 的表达式。 谓词用于WHERE子句和HAVING子句的搜索条件中,还用于FROM子句的联接条件以及需要布尔值的其他构造中。官方的解释为:A predicate is an expression that evaluates to True or False 。在WHERE条里面的常见的谓词形式有:
1: LIKE模糊查询。
2: BETWEEN范围查询
3: IS NULL、IS NOT NULL判断
4: IN - OR
5: EXIST
6: 等值查询
..............................
边界相交是指多个边界的逻辑与(即AND)操作。例如,给定两个边界[[3,Infinity]]和[[-Infinity,6]],边界的交点将得出[[3,6]]。
注释: infinity 无限; 无穷。表示无穷的符号是(∞),为了便于理解,后文用符号∞来代替infinity。
给定一个数组字段的索引,请考虑一个查询,该查询在数组上指定多个谓词并且可以使用多键索引。如果$elemMatch加入谓词,MongoDB让多键索引边界相交。
例如,一个叫survey的集合包含带有字段item和数组字段ratings的文档:
{ _id: 1, item: "ABC", ratings: [ 2, 9 ] }
{ _id: 2, item: "XYZ", ratings: [ 4, 3 ] }
在ratings数组上创建一个多键索引:
db.survey.createIndex( { ratings: 1 } )
以下查询使用$elemMatch要求数组中至少包含一个元素要同时匹配两个条件:
db.survey.find( { ratings : { $elemMatch: { $gte: 3, $lte: 6 } } } )
将谓词分开:
由于查询语句使用$elemMatch连接这些谓词,因此MongoDB可以将边界逻辑与运算:ratings: [ [ 3, 6 ] ]
如果查询未使用$ elemMatch联接数组字段上的条件,则MongoDB无法将多键索引界限进行与运算。考虑以下查询:
db.survey.find( { ratings : { $gte: 3, $lte: 6 } } )
该查询在ratings数组中搜索至少一个大于或等于3的元素以及至少一个小于或等于6的元素。由于单个元素不需要同时满足两个条件,因此MongoDB不会将界限与运算,并且使用其中一个 [ [ 3, ∞] ] 或[ [ -∞, 6 ] ]。 MongoDB不保证选择这两个界限中的哪一个。
复合边界是指对复合索引的多键使用边界。例如,给定一个复合索引{a:1,b:1},其字段a上的边界[ [ 3, ∞] ],字段b上的边界[ [ -∞, 6 ] ],则将边界复合会导致使用两个界限:
{ a: [ [ 3, ∞] ], b: [ [ -∞, 6 ] ] }
如果MongoDB无法将这两个边界组合在一起,则MongoDB始终通过其前导字段的边界来限制索引扫描,在这种情况下,a: [ [ 3, ∞] ]。
考虑一个复合多键索引(其中一个索引字段是数组的复合索引)。例如,一个集合survey包含带有一个字段 item 和一个数组字段ratings的文档:
{ _id: 1, item: "ABC", ratings: [ 2, 9 ] }
{ _id: 2, item: "XYZ", ratings: [ 4, 3 ] }
在item字段和ratings字段上创建复合索引:
db.survey.createIndex( { item: 1, ratings: 1 } )
以下查询在索引的两个键上指定一个条件:
db.survey.find( { item: "XYZ", ratings: { $gte: 3 } } )
将谓词分解:
MongoDB可以将两个边界组合起来以使用以下组合的边界:
{ item: [ [ "XYZ", "XYZ" ] ], ratings: [ [ 3, ∞] ] }
标量字段是其值既不是文档也不是数组的字段。例如一个值为字符串或整数的字段是标量字段。
标量字段可以是嵌套在文档中的字段,只要该字段本身不是数组或文档即可。例如,在文档{a:{b:{c:5,d:5}}}中,c和d是标量字段,而a和b不是。
标量类型(Scalar type)是相对复合类型(Compound type)来说的:标量类型只能有一个值,而复合类型可以包含多个值。复合类型是由标量类型构成的。
在C语言中,整数类型(int、short、long等)、字符类型(char、wchar_t等)、枚举类型(enum)、小数类型(float、double等)、布尔类型(bool)都属于标量类型,一份标量类型的数据只能包含一个值。例如:int n = 100;n 就表示100这一个整数。当然,n的值可以被改变,但无论如何,都只能表示一个值。
结构体(struct)、数组都属于复合类型,一份复合类型的数据可以包含多个标量类型的值,也可以包含其他复合类型的值。例如:int nums[ ] = { 5, 38, 49, 92 };
在版本3.4中进行了更改:仅对于WiredTiger和内存中存储引擎
从MongoDB 3.4开始,对于使用MongoDB 3.4或更高版本创建的多键索引,MongoDB跟踪一个或多个多键索引字段。跟踪此信息使MongoDB的查询索引边界更严格。
示例文档:survey
{ _id: 1, item: "ABC", ratings: [ 2, 9 ] }
{ _id: 2, item: "XYZ", ratings: [ 4, 3 ] }
上述复合索引位于标量字段 item和数组字段ratings上:
db.survey.createIndex( { item: 1, ratings: 1 } )
对于WiredTiger和In-Memory存储引擎,如果查询操作在MongoDB 3.4或更高版本中创建的复合多键索引标量字段上指定多个谓词,则MongoDB将与该字段的边界相交。
例如,以下操作在标量字段上指定范围查询以及在数组字段上指定范围查询:
db.survey.find( {
item: { $gte: "L", $lte: "Z"}, ratings : { $elemMatch: { $gte: 3, $lte: 6 } }
} )
MongoDB将把item的边界相交后为[ [ "L", "Z" ] ] ,并将ratings的边界相交后为[[3.0, 6.0]],以使用以下组合的边界:
"item" : [ [ "L", "Z" ] ], "ratings" : [ [3.0, 6.0] ]
再举一个例子,考虑标量字段属于嵌套文档的位置。例如,survey 集合包含以下文档:
{ _id: 1, item: { name: "ABC", manufactured: 2016 }, ratings: [ 2, 9 ] }
{ _id: 2, item: { name: "XYZ", manufactured: 2013 }, ratings: [ 4, 3 ] }
在标量字段“ item.name”,“ item.manufactured”和数组字段ratings 上创建复合多键索引:
db.survey.createIndex( { "item.name": 1, "item.manufactured": 1, ratings: 1 } )
考虑以下在标量字段上指定查询谓词的操作:
db.survey.find( {
"item.name": "L" ,
item.manufactured": 2012
} )
对于此查询,MongoDB可以使用以下组合范围:
"item.name" : [ ["L", "L"] ], "item.manufactured" : [ [2012.0, 2012.0] ]
MongoDB的早期版本无法将这些范围组合为标量字段。
如果数组包含嵌入式文档,则要在嵌入式文档中的字段上建立索引,请在索引规范中使用虚线的字段名称(点操作符)。例如,给定以下嵌入式文档数组:
ratings: [ { score: 2, by: "mn" }, { score: 9, by: "anon" } ]
score 字段的索引字段名称为“ratings.score”。
考虑一个集合survey2包含具有字段item和数组字段ratings的文档:
{
_id: 1,
item: "ABC",
ratings: [ { score: 2, by: "mn" }, { score: 9, by: "anon" } ]
},
{
_id: 2,
item: "XYZ",
ratings: [ { score: 5, by: "anon" }, { score: 7, by: "wv" } ]
}
在非数组字段item 以及数组ratings.score和ratings.by的两个字段上创建复合索引:
db.survey2.createIndex( { "item": 1, "ratings.score": 1, "ratings.by": 1 } )
下面的查询指定了所有三个字段的条件:
db.survey2.find( { item: "XYZ", "ratings.score": { $lte: 5 }, "ratings.by": "anon" } )
将谓词分解后:
MongoDB可以根据查询谓词和索引键值,将item键的范围与"ratings.score"的范围或"ratings.by"的范围组合在一起。 MongoDB不保证哪个字段与item字段的边界进行复合。例如,MongoDB将选择将item边界与"ratings.score"边界进行复合:
{
"item" : [ [ "XYZ", "XYZ" ] ],
"ratings.score" : [ [ -Infinity, 5 ] ],
"ratings.by" : [ [ MinKey, MaxKey ] ]
}
或者,MongoDB可以选择将item边界与"ratings.by"边界进行复合:
{
"item" : [ [ "XYZ", "XYZ" ] ],
"ratings.score" : [ [ MinKey, MaxKey ] ],
"ratings.by" : [ [ "anon", "anon" ] ]
}
但是,要将"ratings.score"的界限与" ratings.by"的界限混合在一起,查询必须使用$ elemMatch。有关更多信息,请参见数组中索引字段的复合边界。
要将来自同一数组的索引键的边界复合在一起,索引键必须共享相同的字段路径,但不能超过字段名称,并且查询必须指定字段上的谓词在该路径上使用$elemMatch。
对于嵌入式文档中的字段,点字段名称(例如“ a.b.c.d”)是d的字段路径。要复合来自同一数组的索引键的边界,$elemMatch必须位于直到但不包括字段名称本身的路径上;即“ a.b.c”。
例如,在ratings.score和ratings.by字段上创建复合索引:
db.survey2.createIndex( { "ratings.score": 1, "ratings.by": 1 } )
字段“ ratings.score”和“ ratings.by”共享字段路径ratings。以下查询在字段ratings 上使用$ elemMatch,要求数组包含至少一个与两个条件都匹配的元素:
db.survey2.find( { ratings: { $elemMatch: { score: { $lte: 5 }, by: "anon" } } } )
将谓词分解:
MongoDB可以将两个边界组合起来以使用以下组合的边界:
{"ratings.score" : [ [ -∞, 5 ] ], "ratings.by" : [ [ "anon", "anon" ] ] }
如果查询未使用$elemMatch联接索引数组字段中的条件,则MongoDB无法复合其边界。考虑以下查询:
db.survey2.find( { "ratings.score": { $lte: 5 }, "ratings.by": "anon" } )
由于数组中的单个嵌入式文档不需要同时满足两个条件,因此MongoDB不会增加界限。使用复合索引时,如果MongoDB无法约束索引的所有字段,则MongoDB始终会约束索引的前导字段,在这种情况下为“ ratings.score”:
{
"ratings.score": [ [ -Infinity, 5 ] ],
"ratings.by": [ [ MinKey, MaxKey ] ]
}
如果查询未在嵌入字段的路径上指定$elemMatch(最多但不包括字段名),则MongoDB无法复合来自同一数组的索引键的范围。
例如,集合Survey3包含具有字段项和数组字段等级的文档:
{
_id: 1,
item: "ABC",
ratings: [ { scores: [ { q1: 2, q2: 4 }, { q1: 3, q2: 8 } ], loc: "A" },
{ scores: [ { q1: 2, q2: 5 } ], loc: "B" } ]
},
{
_id: 2,
item: "XYZ",
ratings: [ { scores: [ { q1: 7 }, { q1: 2, q2: 8 } ], loc: "B" } ]
}
在ratings.scores.q1和ratings.scores.q2字段上创建复合索引:
db.survey3.createIndex( { "ratings.scores.q1": 1, "ratings.scores.q2": 1 } )
字段“ ratings.scores.q1”和“ ratings.scores.q2”共享字段路径“ ratings.scores”,并且$elemMatch必须在该路径上。
但是,以下查询使用$elemMatch,但未在所需路径上使用:
db.survey3.find( { ratings: { $elemMatch: { ‘scores.q1‘: 2, ‘scores.q2‘: 8 } } } )
因此,MongoDB无法合并边界,并且在索引扫描期间“ ratings.scores.q2”字段将不受限制。要增加界限,查询必须在路径“ratings.scores”上使用$elemMatch:
db.survey3.find( { ‘ratings.scores‘: { $elemMatch: { ‘q1‘: 2, ‘q2‘: 8 } } } )
MongoDB 可以使用多个索引的交集来实现查询。通常,每个索引交集都包含两个索引; 但是,MongoDB 可以使用多个/嵌套索引交集来解决查询。
为了说明索引交集,考虑一个具有以下索引的集合顺序:
{ qty: 1 }
{ item: 1 }
可以使用两个索引的交集来支持以下查询:
db.orders.find( { item: "abc123", qty: { $gt: 15 } } )
为确认 MongoDB 是否使用了交叉索引,可以用 explain() 函数看结果是否包含一个 AND_SORTED stage 或一个 AND_HASH stage。
用交叉索引,MongoDB 即可以用整个索引的交叉也可以用前缀索引的交叉。前缀索引(index prefix)是复合索引(compound index)的子集,由索引从开始字段起始的一个或多个字段组成。
考虑在 orders 集合上有以下索引:
{ qty: 1 }
{ status: 1, ord_date: -1 }
为了满足下列指定在既有 qty 又有 status 字段的查询条件,MongoDB 可以用这两个索引的交叉。
db.orders.find( { qty: { $gt: 10 } , status: "A" } )
交叉索引不会消除对创建复合索引的需要。因为索引中字段的列举顺序和排序顺序(升序或降序)在复合索引中都很重要。一个复合索引可能不支持对于不包含索引前缀字段或指定了不同的排序顺序的查询条件。
例如,一个 orders 集合有如下复合索引,status 在 ord_date 之前:
{ status: 1, ord_date: -1 }
这个复合索引可以支持以下查询:
db.orders.find( { status: { $in: ["A", "P" ] } } )
db.orders.find(
{
ord_date: { $gt: new Date("2014-02-01") },
status: {$in:[ "P", "A" ] }
}
)
但不支持以下查询:
db.orders.find( { ord_date: { $gt: new Date("2014-02-01") } } )
db.orders.find( { } ).sort( { ord_date: 1 } )
但是,如果这个集合有以下两个单独的索引:
{ status: 1 }
{ ord_date: -1 }
那么,这两个索引可以或者分别或者通过交叉索引,支持前面提到的(aforementioned)四个查询。
是选择创建复合索引支持你的查询还是用交叉索引,依赖于你的系统的具体细节。
当 sort() 操作要求的一个完整的索引与查询谓词命中的索引完全分离时,交叉索引不会被应用。
例如,集合 orders 上有以下索引:
{ qty: 1 }
{ status: 1, ord_date: -1 }
{ status: 1 }
{ ord_date: -1 }
MongoDB 不能用交叉索引满足以下查询:
db.orders.find( { qty: { $gt: 10 } } ).sort( { status: 1 } )
就是说,MongoDB 不能用 { qty: 1 } 索引来查询,同时,用完全分离的 { status: 1 } 索引或 { status: 1, ord_date: -1 } 索引来排序。
然而,以下查询中,由于 { status: 1, ord_date: -1 } 可以满足部分查询谓词,所以 MongoDB 可以使用交叉索引:
db.orders.find( { qty: { $gt: 10 } , status: "A" } ).sort( { ord_date: -1 } )
为了支持对字符串内容的文本搜索查询,MongoDB提供了文本索引。文本(text )索引可以包含任何值为字符串或字符串元素数组的字段。
文本索引版本 | 描述 |
---|---|
版本3 | MongoDB引入了文本索引的版本3。版本3是在MongoDB 3.2及更高版本中创建的文本索引的默认版本。 |
版本2 | MongoDB 2.6引入了文本索引的版本2。版本2是在MongoDB 2.6和3.0系列中创建的文本索引的默认版本。 |
版本1 | MongoDB 2.4引入了文本索引的版本1。 MongoDB 2.4仅支持版本1。 |
要覆盖默认版本并指定其他版本,请在创建索引时包含选项:{ "textIndexVersion":
重要:
一个集合最多有一个文本索引。
要创建文本索引,请使用db.collection.createIndex()方法。
要为包含字符串或字符串元素数组的字段建立索引,请包括该索引字段并指定字符串符号“text”,如以下示例所示:
db.reviews.createIndex( { comments: "text" } )
您可以为多个字段建立文本索引。以下示例在subject 和 comments字段上创建文本索引:
db.reviews.createIndex(
{
subject: "text",
comments: "text"
}
)
复合索引可以包括文本索引键以及升/降索引键。有关更多信息,请参见复合索引。
为了删除文本索引,请使用索引名称。有关更多信息,请参见使用索引名称删除文本索引。
对于文本索引,索引字段的权重表示该字段相对于其他索引字段在文本搜索得分方面的重要性。
对于文档中的每个索引字段,MongoDB 将匹配数乘以权重并将结果加总。然后使用这个和,MongoDB 计算文档的得分。有关返回和按文本分数排序的详细信息,请参阅 $meta 操作符。
索引字段的默认权重为1。若要调整索引字段的权重,请在 db.collection.createIndex ()方法中包含权重选项。
待补充......
标签:city tree 实现 创建 方法 float RoCE 限制 --
原文地址:https://www.cnblogs.com/wyj944407830/p/13949724.html