# Sparse 索引

**在本页面**

* [创建sparse索引](#创建)
* [行为](#行为)
* [例子](#例子)

Sparse索引只包含有索引字段的文档的条目，即使索引字段包含空值。索引会跳过任何缺少索引字段的文档。索引是\*\*“稀疏的”\*\*，因为它不包括一个集合的所有文档。相反，非稀疏索引包含集合中的所有文档，为那些不包含索引字段的文档存储空值。

> 重要的
>
> 从MongoDB 3.2开始，MongoDB提供了创建[部分索引](https://docs.mongodb.com/master/core/index-partial/#index-type-partial)的选项。部分索引提供了sparse索引功能的超集。如果你正在使用MongoDB 3.2或更高版本，[部分索引](https://docs.mongodb.com/master/core/index-partial/#index-type-partial)应该比稀疏索引更受欢迎。

## 创建sparse索引

要创建一个\*\*“sparse”**索引，使用**[**db.collection.createIndex()**](https://docs.mongodb.com/master/reference/db.collection.createindex%20/#db.collection.createIndex)**方法，并将**“sparse”**选项设置为**“true”**。例如，下面的操作在**[**mongo**](https://docs.mongodb.com/master/reference/program/mongo/#bin.mongo) **shell中创建了一个稀疏的索引在**xmpp\_id\*\*字段的地址集合:

```
db.addresses.createIndex( { "xmpp_id": 1 }, { sparse: true } )
```

索引不会索引不包含\*\*“xmpp\_id”\*\*字段的文档。

> 注意
>
> 不要将MongoDB中的sparse索引与其他数据库中的[块级](http://en.wikipedia.org/wiki/Database_index#Sparse_index)索引混淆。可以将它们看作具有特定过滤器的密集索引。

## 行为

### “Sparse”索引和不完整结果

如果sparse索引会导致查询和排序操作的结果集不完整，MongoDB将不会使用该索引，除非[hint()](https://docs.mongodb.com/master/reference/method/cursor.hint/#cursor.hint)明确指定该索引。

例如，查询`{x: {$exists: false}}`不会在**x**字段上使用sparse索引，除非有明确提示。参见[集合上的稀疏索引不能返回完整的结果](https://docs.mongodb.com/master/core/index-sparse/#%20spars-index-incomplet-results)了解详细的行为示例。

*Changed in version 3.4*.

如果在执行集合中所有文档的count()(i.e.带有空查询谓词)时包含 [sparse索引](https://docs.mongodb.com/master/core/index-sparse/#index-type-sparse)[`count()`](https://docs.mongodb.com/master/reference/method/cursor.count/#cursor.count)，则即使sparse索引导致计数不正确，也会使用sparse索引。

```
db.collection.insert({ _id: 1, y: 1 } );
db.collection.createIndex( { x: 1 }, { sparse: true } );

db.collection.find().hint( { x: 1 } ).count();
```

要获得正确的计数，在对集合中的所有文档执行计数时，不要使用[sparse索引](https://docs.mongodb.com/master/core/index-sparse/#index-type-sparse)的\*\*“hint()\*\*”。

```
db.collection.find().count();

db.collection.createIndex({ y: 1 });
db.collection.find().hint({ y: 1 }).count();
```

### 默认情况下是“sparse”的索引

[2dsphere(版本2)](https://docs.mongodb.com/master/core/2dsphere/#dsphere-v2)，[ 2d](https://docs.mongodb.com/master/core/2d/)， [geoHaystack](https://docs.mongodb.com/master/core/geohaystack/)和[文本](https://docs.mongodb.com/master/core/index-text/)索引始终为`sparse`。

### Sparse复合索引

Sparse[复合索引](https://docs.mongodb.com/master/core/index-compound/)只包含升序/降序索引键将索引一个文档，只要该文档包含至少一个键。

包含一个地理空间的稀疏的复合索引键(即[2 dsphere](https://docs.mongodb.com/master/core/2dsphere/), [2d](https://docs.mongodb.com/master/core/2d/),或[geoHaystack](https://docs.mongodb.com/master/core/geohaystack/)索引键)连同升序/降序索引键,只有地理空间的存在领域(s)文档中确定索引文档的引用。

对于包含[text](https://docs.mongodb.com/master/core/index-text/)索引键和升序/降序索引键的sparse复合索引，只有\*\*“text”\*\*索引字段的存在决定该索引是否引用一个文档。

### “Sparse”和“unique”属性

一个\*\*“sparse”\*\*和[unique](https://docs.mongodb.com/master/core/index-unique/#index-type-unique)索引可以防止集合的文档具有一个字段的重复值，但允许多个文档忽略该键。

## 例子

### 在集合上创建sparse索引

考虑一个包含以下文档的集合\*\*“scores”\*\*:

```
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
```

集合在\*\*“score”**字段上有一个**sparse\*\*索引:

```
db.scores.createIndex( { score: 1 } , { sparse: true } )
```

然后，下面对**scores**集合的查询使用sparse索引返回**score**字段小于([' $lt '](https://docs.mongodb.com/master/reference/operator/query/lt/#op._S_lt))的文档**90**:

```
db.scores.find( { score: { $lt: 90 } } )
```

由于userid的文档`"newbie"`不包含该 `score`字段，因此不满足查询条件，因此查询可以使用sparse索引返回结果：

```
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
```

### 集合上的sparse索引不能返回完整的结果

考虑一个包含以下文档的集合“**scores**”:

```
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
```

集合在\*\*“score”\*\*字段上有一个sparse索引:

```
db.scores.createIndex( { score: 1 } , { sparse: true } )
```

因为userid的文档 `"newbie"`不包含`score`字段，所以sparse索引不包含该文档的条目。

考虑以下查询返回`scores`集合中的**所有**文档，按`score`字段排序:

```
db.scores.find().sort( { score: -1 } )
```

即使是按索引字段排序，MongoDB也不会选择sparse索引来完成查询，以返回完整的结果:

```
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
```

要使用sparse索引，显式地用`hint()`指定索引:

```
db.scores.find().sort( { score: -1 } ).hint( { score: 1 } )
```

使用索引只返回那些带有`score`字段的文档:

```
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
```

也可以看看：

[`explain()`](https://docs.mongodb.com/master/reference/method/cursor.explain/#cursor.explain) 和 [Analyze Query Performance](https://docs.mongodb.com/master/tutorial/analyze-query-plan/)

## 具有唯一约束的sparse索引

考虑一个包含以下文档的集合**scores**:

```
{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "userid" : "newbie" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "userid" : "abby", "score" : 82 }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "userid" : "nina", "score" : 90 }
```

您可以使用以下操作在**score**字段上创建一个[unique constraint](https://docs.mongodb.com/master/core/index-unique/#index-type-unique)和sparse过滤器:

```
db.scores.createIndex( { score: 1 } , { sparse: true, unique: true } )
```

该索引将允许插入具有该`score`字段唯一值或不包含该`score`字段的文档。这样，鉴于`scores`集合中现有的文档，索引允许进行以下[插入操作](https://docs.mongodb.com/master/tutorial/insert-documents/)：

```
db.scores.insert( { "userid": "AAAAAAA", "score": 43 } )
db.scores.insert( { "userid": "BBBBBBB", "score": 34 } )
db.scores.insert( { "userid": "CCCCCCC" } )
db.scores.insert( { "userid": "DDDDDDD" } )
```

但是，索引不允许添加以下文件，因为文件已经存在，其**score**值为**82**和**90**:

```
db.scores.insert( { "userid": "AAAAAAA", "score": 82 } )
db.scores.insert( { "userid": "BBBBBBB", "score": 90 } )
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mongoing.com/indexes/index-properties/sparse-indexes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
