从数组中查找 & 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
我如何找到 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