MongoDB查询标准和预测

时间:2013-10-30 14:15:20

标签: node.js mongodb express mongoskin

我使用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年,当前年份。

我猜投影是我需要的,但问题是投影只返回它找到的第一个结果......

4 个答案:

答案 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/

  • 使用标准的mongo查询shell,默认情况下仅限于分页结果集,其中键入“it”将遍历结果。

答案 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数组,然后只保留指定年份的发票,并将最后匹配的发票分组到客户字段中。