查询以清楚地获取每个股票代码的最新报价

时间:2015-02-25 04:28:25

标签: mongodb meteor

在Meteor中,我有一个价格报价的报价集合,它是所有跟踪符号的混合。行情集合如下所示:

{ "sym" : "CL", "bid" : 49.29, "ask" : 49.31, "timestamp" : 1424835506105, "_id" : "2yPrQzoZ8MTad8viw" }
{ "sym" : "CL", "bid" : 49.3, "ask" : 49.31, "timestamp" : 1424835512114, "_id" : "oMcsLm2qqkLqWDxpG" }
{ "sym" : "ZB", "bid" : 146.0625, "ask" : 146.09375, "timestamp" : 1424835529244, "_id" : "7XSDNAR8Hx6DmjWhg" }
{ "sym" : "NQ", "bid" : 4445.25, "ask" : 4445.75, "timestamp" : 1424835533854, "_id" : "3AgfZWYAbnWW7pGcc" }
{ "sym" : "YM", "bid" : 18181, "ask" : 18182, "timestamp" : 1424835540869, "_id" : "AQupJnnx2mNMLwSq5" }
{ "sym" : "ZB", "bid" : 146.0625, "ask" : 146.125, "timestamp" : 1424835540870, "_id" : "85eemh5pPQd469cMK" }
{ "sym" : "NQ", "bid" : 4445.25, "ask" : 4445.5, "timestamp" : 1424835540883, "_id" : "7cMmsJqoAkct2CPtm" }
{ "sym" : "NQ", "bid" : 4445.25, "ask" : 4445.75, "timestamp" : 1424835546572, "_id" : "r7zNAuqeQXL7jvnDv" }
{ "sym" : "YM", "bid" : 18181, "ask" : 18183, "timestamp" : 1424835546573, "_id" : "7Dxf2WmhibBuuZrg2" }
{ "sym" : "ES", "bid" : 2112.5, "ask" : 2113, "timestamp" : 1424835577420, "_id" : "yWKtqNjbtSoN2dMzc" }
{ "sym" : "YM", "bid" : 18181, "ask" : 18182, "timestamp" : 1424835577438, "_id" : "bWmmtvdAafxgaNRNJ" }

我想只检索每个sym的最新报价,这意味着我需要将sym上的不同与最大时间戳结合起来。我在Meteor中这样做。

是否有一个Quotes.find()命令会返回此结果集?

{ "sym" : "CL", "bid" : 49.3, "ask" : 49.31, "timestamp" : 1424835512114, "_id" : "oMcsLm2qqkLqWDxpG" }
{ "sym" : "ZB", "bid" : 146.0625, "ask" : 146.125, "timestamp" : 1424835540870, "_id" : "85eemh5pPQd469cMK" }
{ "sym" : "NQ", "bid" : 4445.25, "ask" : 4445.75, "timestamp" : 1424835546572, "_id" : "r7zNAuqeQXL7jvnDv" }
{ "sym" : "ES", "bid" : 2112.5, "ask" : 2113, "timestamp" : 1424835577420, "_id" : "yWKtqNjbtSoN2dMzc" }
{ "sym" : "YM", "bid" : 18181, "ask" : 18182, "timestamp" : 1424835577438, "_id" : "bWmmtvdAafxgaNRNJ" }

3 个答案:

答案 0 :(得分:1)

截至Meteor 1.0.3.2 aggregate function is not supported

但是基于the meteor docs的示例,您可以在发布函数中观察服务器上集合的更改,并返回带有聚合值的动态集合。

以下是这对你的情况有用:

// server: publish the current size of a collection
Meteor.publish("recentQuotes", function () {
  var self = this;

  // here we'll store information about which documents are used
  // as the most recent ones
  var onlyLastValues = {};

  var handle = Quotes.find({}, {sort: {timestamp: 1}}).observeChanges({

    // fired when a document is added to the Quotes collection
    added: function (id, fields) {

      if (onlyLastValues[fields.sym] === undefined)
        self.added("recentQuotesAll", fields.sym, fields);   
      else
        self.changed("recentQuotesAll", fields.sym, fields);  

      onlyLastValues[fields.sym] = id;

    },

    // fired when a document is removed from the Quotes collection
    // if that's one
    removed: function (id) {

      // as you only have id as a parameter you need to find  
      // which sym was changed

      onlyLastValuesById = _.invert(onlyLastValues);

      if (onlyLastValuesById[id] !== undefined){
        // the removed document was one of the last documents

        // search for last quote with that sym
        lastQuote = Quotes.findOne({sym: onlyLastValuesById[id]}, {sort: {timestamp: -1}});

        // remove if it was the last one
        if (lastQuote === undefined)
          self.removed("recentQuotesAll", onlyLastValuesById[id]); 

        else
          // modify the dynamic collection
          self.changed("recentQuotesAll", lastQuote.sym, lastQuote);    
      }

    },

    // fired when the document in Quotes collection is changed
    // need to check if that's one of the last quotes
    changed: function(id, fields){

      // this is fairly similar to removed

      onlyLastValuesById = _.invert(onlyLastValues);

      if (onlyLastValuesById[id] !== undefined){

        // this time we have all the fields already

        // modify the dynamic collection
        self.changed("recentQuotesAll", fields.sym, fields);    
      }
    }

  });

  self.ready();

  // Stop observing the cursor when client unsubs.
  // Stopping a subscription automatically takes
  // care of sending the client any removed messages.
  self.onStop(function () {
    handle.stop();
  });
});

}

if (Meteor.isClient){

// client: declare collection to hold aggregated object
RecentQuotesAll = new Mongo.Collection("recentQuotesAll");

// client: subscribe to the aggregated values
Tracker.autorun(function () {
  Meteor.subscribe("recentQuotes");
});

您还可以添加initializing变量,以便在首次完全计算数据后发布数据。为此,您必须在onlyLastValues对象中存储所有字段,并为每个存储的值运行self.addedself.ready(); 调用

答案 1 :(得分:0)

我不知道如何在meteor中查询,但在mongo聚合下面会解决您的问题

    db.collectionName.aggregate({
    "$sort": {
    "timestamp": -1
    }
}, {
    "$group": {
    "_id": "$sym",
    "bid": {
        "$first": "$bid"
    },
    "ask": {
        "$first": "$ask"
    },
    "timestamp": {
        "$first": "$timestamp"
    },
    "id": {
        "$first": "$_id"
    }
    }
}, {
    "$project": {
    "sym": "$_id",
    "bid": "$bid",
    "ask": "$ask",
    "timestamp": "$timestamp",
    "_id": "$id"
    }
})

答案 2 :(得分:0)

试试这个 -

db.collection.aggregate({ "$group" : {"_id" : "$sym",
     "runtime" : {"$max" : "$timestamp"},
"bid":{$last:"$bid"},
"ask":{$last:"$ask"}
 }},

{ "$project" : {
     "sym" : "$_id" ,
     "runtime" : 1,
    "bid":1,
    "ask":1
 }
})