将Mongo输出与用于API的节点组合

时间:2014-06-20 20:48:37

标签: node.js mongodb asynchronous express keystonejs

我对Node非常陌生,但我目前有一个NodeJS / Express开源CMS,并希望为我正在使用的应用输出一些API数据。请原谅我,如果我没有使用正确的术语或其他什么,这对我来说是新的。

我目前拥有的是两个馆藏,地点和旅游。 CMS允许我在两者之间建立关系。这只是在每个相关游览记录的位置记录中存储一个ObjectID数组。

我想要做的是获取我的API输出代码(下面)并让它输出整个巡视阵列,包括所有字段(标题,描述等),以及每个位置记录。目前它只输出ID的数组。

这是我目前的代码:

var async = require('async'),
 landmark = require('keystone');

var Location = keystone.list('Location'),
        Tour = keystone.list('Tour');

    /**
     * List Locations
     */
    exports.list = function(req, res) {
        Location.model.find(function(err, items) {

            if (err) return res.apiError('database error', err);

            res.apiResponse({
                locations: items
            });

        });
    }

    /**
     * Get Location by ID
     */
    exports.get = function(req, res) {
        Location.model.findById(req.params.id).exec(function(err, item) {

            if (err) return res.apiError('database error', err);
            if (!item) return res.apiError('not found');

            res.apiResponse({
                location: item
            });

        });
    }

当前API输出(截断):

{
  "locations": [
    {
      "_id": "53a47997ebe91d8a4a26d251",
      "slug": "test-location",
      "lastModified": "2014-06-20T20:19:14.484Z",
      "commonName": "test location",
      "__v": 3,
      "url": "",
      "tours": [
        "53a47963ebe91d8a4a26d250"
      ],
      "images": []
    }
  ]
}

我在寻找:

{
  "locations": [
    {
      "_id": "53a47997ebe91d8a4a26d251",
      "slug": "test-location",
      "lastModified": "2014-06-20T20:19:14.484Z",
      "commonName": "test location",
      "__v": 3,
      "url": "",
      "tours": [
        {
           "_id": "53a47963ebe91d8a4a26d250",
           "title": "my test tour title",
           "url": "url_to_audio_file"
        }
      ],
      "images": []
    }
  ]
}

任何人都知道这是否可行?任何帮助,将不胜感激!谢谢!

2 个答案:

答案 0 :(得分:0)

看起来像,就像您已设置Location模型以引用Tour一样,定义为Tour的数组。这意味着,当您在Tour中存储Location时,您不会存储代表Tour的数据,而是存储引用Tour的ID。当您执行find操作时,您会在响应中看到您发送回客户端。

如果是这种情况,那么您可能需要查看Mongoose's populate function。这将采用这些引用并使用它们包含的数据完全填充它们。

例如,您可以将查询更改为以下内容:

Location.model.find().populate('tours').exec(function(err, items) {
    // items should now contain fully populated tours
}

如果这不是您的意思,请告诉我,我可以尝试进一步提供帮助。

答案 1 :(得分:0)

@dylants提供的解决方案绝对正确。但是,要使其正常工作,您需要在tours列表中将Types.Relationship声明为Location字段,并将ref选项设置为Tour

查看Relationship Fields上的Keystone文档。

我在下面的示例中添加了manytrue选项,因为我认为这是一对多的关系。如果不是,你可以丢弃它。

var keystone = require('keystone'),
  Location = keystone.list('Location');

Location.add({
   ...
   tours: { type: Types.Relationship, ref: 'Tour', many: true },
   ...
});

您提到的List.relationship()方法仅在您希望相关文档列表自动显示在Keystone Admin UI中时使用,而不是用于建立实际关系。

希望这有帮助。