我使用Node / Express / MongoDB / Mongoskin构建应用程序。
我在数据库中有一个集合namned" clients",其中包含有关客户帐户信息的文档。每个客户端文档都包含一个包含发票对象的数组,如下所示:
doc.invoices = [
{year: 2012,
quarter: 1,
daily: 912.00,
sms: 42.00,
paid: true},
{year: 2012,
quarter: 2,
daily: 913.00,
sms: 55.00,
paid: true},
{year: 2012,
quarter: 3,
daily: 876.00,
sms: 82.00,
paid: true},
{year: 2012,
quarter: 4,
daily: 903.00,
sms: 93.00,
paid: false},
{year: 2013,
quarter: 1,
daily: 915.00,
sms: 67.00,
paid: true},
{year: 2013,
quarter: 2,
daily: 920.00,
sms: 35.00,
paid: true},
{year: 2013,
quarter: 3,
daily: 880.00,
sms: 92.00,
paid: true},
{year: 2013,
quarter: 4,
daily: 900.00,
sms: 85.00,
paid: false}
]
问题:让我们说我想查询此集合中的所有文档,例如显示所有客户端的Superadmin视图,但我想将发票数组返回的信息限制为其中的对象"一年"等于某个值,例如2013年,当前年份。
我猜投影是我需要的,但问题是投影只返回它找到的第一个结果......
答案 0 :(得分:6)
首先,投影不会返回它发现的第一个结果,它告诉mongo返回什么。
.findOne(查询)将LIMIT结果置于一个或查找(查询).limit(1)也将执行相同的操作。
你说你想要“全部”获取你的数据。
标准查找类型查询将启动您的...
find({mongo:query},{mongo:projection})
但将结果限制为来自mongo shell *
的游标因为你说你使用express.js你可以使用javascript函数来“返回所有”这样的简单查找结果......
db.sales.find({"year":2013},{_id:0,"year":1,"quarter":1,"daily":1,"sms":1,"paid":1})
首先设置到函数的路径
app.get('/sales/yr/:yr', sales.getAllResults);
然后是一个处理简单mongo查询和投影的函数。
/**
* get ALL results given YEAR ONLY
* extend jsonQuery to modify results
* extend or reduce jsonProjection to control data returned
*/
exports.getAllResults= function(req, res) {
var yr = req.params.yr ;
var jsonQuery = {"year":yr} ; //add or remove comma seperated "key":values given your JSON collection
var jsonProjection = {_id:0,"year":1,"quarter":1,"daily":1,"sms":1,"paid":1} ; //leave year out since that's specified in the query anyhow
var jsort = {"some-thing-else":-1} ; //-1 descending or 1 ascending
db.collection("YOUR-COLLECTION_NAME", function(err, collection) {
collection.find( jsonQuery, jsonProjection).sort(jsort).toArray( function(err, items) {
res.send(items);
});
});
}
最后你可能想要关注express和mongo的教程,有一些好的,我把这个答案放在一起,基于来自Chris Coenraets的优秀启动者看到: -
http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/
答案 1 :(得分:3)
请注意,投影允许我们在MongoDB
查询中明确包含或排除字段。我们使用 1
表示我们要包含一个字段,并 0
表示我们希望排除该字段。请记住,_id
字段是特殊的 -
_id
字段包含在内,除非我们明确排除它此外,由于我们在javascript
工作,我们可以构建我们的项目文档和文档,以便与我们在{{1}中的方式非常相似地插入到我们的集合中} 贝壳。不同的是驱动程序提供了一组我们用来与mongo
交互的类和方法,而MongoDB
shell提供了它自己的API。
W上。河吨。从mongo
开始,CRUD
驱动程序和MongoDB 3.2
shell遵循相同的规范。从mongo
shell开始,您如何访问这些方法及其实现方式各不相同。
mongo
var MongoClient = require('mongodb').MongoClient,
assert = require('assert');
MongoClient.connect('mongodb://localhost:27017/crunchbase', function(err, db) {
assert.equal(err, null);
console.log("Successfully connected to MongoDB.");
var query = {"category_code": "biotech"};
var projection = {"name": 1, "category_code": 1, "_id": 0};
var cursor = db.collection('companies').find(query);
cursor.project(projection);
cursor.forEach(
function(doc) {
console.log(doc.name + " is a " + doc.category_code + " company.");
console.log(doc);
},
function(err) {
assert.equal(err, null);
return db.close();
}
);
});
驱动程序中的当前最佳做法是将node.js
的来电链接到我们的project
,即cursor
。此项调用为查询设置了字段投影。此调用不会强制请求从数据库中检索文档,cursor.project
方法也是如此。而是它为我们的foreach
维护的查询表示添加了一些额外的细节。有许多游标方法,我们可以链接在一起,以完全表达我们希望对我们的cursor
数据库执行的操作。对MongoDB
的调用是同步的。我们将使用光标上的db.collection
方法在此处使用字段cursor
修改projection
。
答案 2 :(得分:0)
不确定我是否理解:
find({year:2013},function(err,clients){})
这会返回当年等于2013年的所有客户,它会返回所有文档字段
您正在讨论的投影用于限制查询返回的字段,我的意思是:
find({year:2013},{year:1,paid:1},function(err,clients){})
这将返回一个对象数组,其中年份为2013年,每个对象获得2个字段(付费和年份)
“{year:1,paid:1}”对象是您的投影仪。
答案 3 :(得分:-1)
正如@JohnnyK在评论中提到的那样,你应该使用MongoDB aggregation framework:
db.clients.aggregate([
{ $unwind: "$invoices" },
{ $match: { "invoices.year": 2013 } },
{ $group: { _id: "$_id", /* other client fields */, invoices: { $push: "$invoices" } } }
]);
首先,您将展开初始invoices
数组,然后只保留指定年份的发票,并将最后匹配的发票分组到客户字段中。