# 查询数据

在记录和集合上都有提供 `get` 方法用于获取单个记录或集合中多个记录的数据。

假设我们已有一个集合 `todos`，其中包含以下格式记录：

```js
[
  {
    _id: 'todo-identifiant-aleatoire',
    _openid: 'user-open-id', // 假设用户的 openid 为 user-open-id
    description: "learn cloud database",
    due: Date("2018-09-01"),
    progress: 20,
    tags: [
      "cloud",
      "database"
    ],
    style: {
      color: 'white',
      size: 'large'
    },
    location: Point(113.33, 23.33), // 113.33°E，23.33°N
    done: false
  },
  {
    _id: 'todo-identifiant-aleatoire-2',
    _openid: 'user-open-id', // 假设用户的 openid 为 user-open-id
    description: "write a novel",
    due: Date("2018-12-25"),
    progress: 50,
    tags: [
      "writing"
    ],
    style: {
      color: 'yellow',
      size: 'normal'
    },
    location: Point(113.22, 23.22), // 113.22°E，23.22°N
    done: false
  }
  // more...
]
```

### 获取一个记录的数据

我们先来看看如何获取一个记录的数据，假设我们已有一个 ID 为 `todo-identifiant-aleatoire` 的在集合 todos 上的记录，那么我们可以通过在该记录的引用调用 `get` 方法获取这个待办事项的数据：

```js
db.collection('todos').doc('todo-identifiant-aleatoire').get({
  success: function(res) {
    // res.data 包含该记录的数据
    console.log(res.data)
  }
})
```

也可以用 Promise 风格调用：

```js
db.collection('todos').doc('todo-identifiant-aleatoire').get().then(res => {
  // res.data 包含该记录的数据
  console.log(res.data)
})
```

### 获取多个记录的数据

我们也可以一次性获取多条记录。通过调用集合上的 `where` 方法可以指定查询条件，再调用 `get` 方法即可只返回满足指定查询条件的记录，比如获取用户的所有未完成的待办事项：

```js
db.collection('todos').where({
  _openid: 'user-open-id',
  done: false
})
.get({
  success: function(res) {
    // res.data 是包含以上定义的两条记录的数组
    console.log(res.data)
  }
})
```

`where` 方法接收一个对象参数，该对象中每个字段和它的值构成一个需满足的匹配条件，各个字段间的关系是 "与" 的关系，即需同时满足这些匹配条件，在这个例子中，就是查询出 todos 集合中 `_openid` 等于 `user-open-id` 且 `done` 等于 `false` 的记录。在查询条件中我们也可以指定匹配一个嵌套字段的值，比如找出自己的标为黄色的待办事项：

```js
db.collection('todos').where({
  _openid: 'user-open-id',
  style: {
    color: 'yellow'
  }
})
.get({
  success: function(res) {
    console.log(res.data)
  }
})
```

也可以用 "点表示法" 表示嵌套字段：

```js
db.collection('todos').where({
  _openid: 'user-open-id',
  'style.color': 'yellow'
})
.get({
  success: function(res) {
    console.log(res.data)
  }
})
```

### 获取一个集合的数据

如果要获取一个集合的数据，比如获取 todos 集合上的所有记录，可以在集合上调用 `get` 方法获取，但通常不建议这么使用，在小程序中我们需要尽量避免一次性获取过量的数据，只应获取必要的数据。为了防止误操作以及保护小程序体验，小程序端在获取集合数据时服务器一次默认并且最多返回 20 条记录，云函数端这个数字则是 100。开发者可以通过 `limit` 方法指定需要获取的记录数量，但小程序端不能超过 20 条，云函数端不能超过 100 条。

```js
db.collection('todos').get({
  success: function(res) {
    // res.data 是一个包含集合中有权限访问的所有记录的数据，不超过 20 条
    console.log(res.data)
  }
})
```

也可以用 Promise 风格调用：

```js
db.collection('todos').get().then(res => {
  // res.data 是一个包含集合中有权限访问的所有记录的数据，不超过 20 条
  console.log(res.data)
})
```

下面是在云函数端获取一个集合所有记录的例子，因为有最多一次取 100 条的限制，因此很可能一个请求无法取出所有数据，需要分批次取：

```javascript
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
const MAX_LIMIT = 100
exports.main = async (event, context) => {
  // 先取出集合记录总数
  const countResult = await db.collection('todos').count()
  const total = countResult.total
  // 计算需分几次取
  const batchTimes = Math.ceil(total / 100)
  // 承载所有读操作的 promise 的数组
  const tasks = []
  for (let i = 0; i < batchTimes; i++) {
    const promise = db.collection('todos').skip(i * MAX_LIMIT).limit(MAX_LIMIT).get()
    tasks.push(promise)
  }
  // 等待所有
  return (await Promise.all(tasks)).reduce((acc, cur) => {
    return {
      data: acc.data.concat(cur.data),
      errMsg: acc.errMsg,
    }
  })
}
```
