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

Posted

技术标签:

【中文标题】从数组中查找并返回第一个匹配的子文档(Meteor / Mongo)【英文标题】:Find & return first matching subdocument from array (Meteor / Mongo) 【发布时间】:2015-05-23 17:30:46 【问题描述】:

如何在“tasks”数组中找到并返回第一个匹配完成的子文档:true?

使用findOne 返回整个文档.. 是否有另一个函数用于返回子文档?


  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()
        ]
      
    ]
  

【问题讨论】:

【参考方案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

【讨论】:

【参考方案2】:

您可以通过 aggregation 执行此操作,您可以在其中利用$match 管道的索引和限制。使用 $unwind 运算符将您的任务数组解构为可以匹配的文档流。由于您只想返回“'tasks' 数组中与已完成匹配的第一个子文档:true”,因此您可以在最后一个管道中使用 $limit 运算符阶段只返回一个子文档:

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 / Mongo)的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB通过***属性和嵌套数组键查找文档,并返回匹配文档的一部分

如何从 Mongo DB 中的子文档数组中删除匹配条件的子文档

Excel - 需要从数组中搜索列表单元格的子字符串,无法获得索引/匹配工作吗?

通过 Meteor / Mongo 返回子文档数组

Meteor Apollo GraphQL 接口:返回一个对象数组并在另一个解析器中调用解析器

第k大-二分查找-1139. 第k大的子数组