从数组中查找 & return 第一个匹配的子文档 (Meteor / Mongo)

Find & return first matching subdocument from array (Meteor / Mongo)

我如何找到 return 'tasks' 数组中匹配完成的第一个子文档:true?

使用 findOne return 整个文档.. return 是否有另一个功能用于子文档?

{
  title: 'awebsite.com'
  company: 'a company'
  companyID: Random.id()
  category: 'website'
  starred: false
  timeline: {
    tasks: [
      {
        name: 'task1'
        completed: true
        todos: [
          {todo: 'something', completed: false, todoID: Random.id()}
          {todo: 'something', completed: false, todoID: Random.id()}
          {todo: 'something', completed: false, todoID: Random.id()}
        ]
      }
      {
        name: 'task2'
        completed: false
        todos: [
          {todo: 'something', completed: false, todoID: Random.id()}
          {todo: 'something', completed: false, todoID: Random.id()}
          {todo: 'something', completed: false, todoID: Random.id()}
        ]
      }
    ]
  }
}

您可以在最后一个管道阶段通过 aggregation where you can take advantage of an index and limit with the $match pipeline. Use the $unwind operator to deconstruct your tasks array into a stream of documents that can then be matched. since you would want to return only "the first subdocument in the 'tasks' array that matches completed: true", you could use the $limit 运算符执行此操作,只 return 一个子文档:

db.collection.aggregate([
  { 
      $match: {
          "timeline.tasks.completed": true
      }
  },
  { 
      $unwind: "$timeline.tasks" 
  },
  { 
      $match: {
          "timeline.tasks.completed": true
      }
  },
  { 
      $group: {
           _id: {
                "tasks": "$timeline.tasks"
           }
      }
  },
  {
      $project: {
          _id: 0,
          tasks: "$_id.tasks"
      }
  },
  {
      $limit: 1
  }
])

结果:

{
    "result" : [ 
        {
            "tasks" : {
                "name" : "task1",
                "completed" : true,
                "todos" : [ 
                    {
                        "todo" : "something",
                        "completed" : false,
                        "todoID" : "jfoe84jn"
                    }, 
                    {
                        "todo" : "something",
                        "completed" : false,
                        "todoID" : "yr934hjs"
                    }, 
                    {
                        "todo" : "something",
                        "completed" : false,
                        "todoID" : "84hdkl0t"
                    }
                ]
            }
        }
    ],
    "ok" : 1
}

Meteor 用户:在撰写本文时(版本 1.0.4.1),不支持客户端聚合。

我想将代码保留在客户端上,也想要响应性,所以这是我的解决方案:

db.projects

// simplified structure

{
      title: 'awebsite.com'
      company: 'a company'
      companyID: Random.id()
      category: 'website'
      starred: false
      tasks: [
          {
            completed: true
            name: 'task1'
            category: 'ideas'
            todos: [
              {todo: 'something', completed: false, todoID: Random.id()}
              {todo: 'something', completed: false, todoID: Random.id()}
              {todo: 'something', completed: false, todoID: Random.id()}
            ]
          }
          {
            completed: false
            name: 'task2'
            category: 'ideas'
            todos: [
              {todo: 'something', completed: false, todoID: Random.id()}
              {todo: 'something', completed: false, todoID: Random.id()}
              {todo: 'something', completed: false, todoID: Random.id()}
            ]
          }
        ]
    }

../projects.coffee

Meteor.subscribe 'projects'
Tasks = new (Mongo.Collection)(null)   //use (null) to create client-only collection

Template.projects.rendered = ->
  results = Projects.findOne { title: 'awebsite.com' },
    fields: tasks: 1

  _.each results.tasks, (task) ->
    Tasks.insert (task)

Template.projects.helpers
  currentTask: ->
    Tasks.findOne completed: false