【问题标题】:Loopback push string to array环回将字符串推送到数组
【发布时间】:2018-08-06 09:30:49
【问题描述】:

我的问题与this question asked in 2016 类似,但遗憾的是没有公认的答案。我也无法使用那里的答案来弄清楚我需要如何完成同样的事情。

我基本上是在尝试向我的数据模型中的数组添加一个新项目。

我当前的数据模型(我想要的)是这样的:

{
   teamId: 'team32',
   teamName: 'Lions',
   players: ['Jack','Ryan','Sam']
}

创建新团队时,会为“玩家”添加一个空数组。没有适合玩家的模型。它只是一个可以保存玩家列表的数组。

如何将新玩家添加到玩家列表(将字符串添加到列表)?我也愿意将其存储为对象而不是字符串。

我的团队模型

{
  "name": "teams",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "teamID": {
      "type": "string",
      "required": true
    },
    "teamName": {
      "type": "string",
      "required": true
    },
    "players":{
      "type":"array",
    }
  },
  "validations": [],
  "relations": {},
  "acls": [],
  "methods": {}
}

team.js

var updateQuery = {players:{$addToSet:{'Mark'}}};

team.update({teamID:'teams32'},updateQuery,
     function(err,data){
         console.log(err,data,'result');
      });

$addToSet 和 $push 都对我使用 MongoDB 和 mongoose 有效。但不知何故似乎不适用于环回。由于在这种情况下 $addToSet 和 $push 都不适合我,我该怎么做?

【问题讨论】:

  • 试试这个team.update( { "teamID": "teams32" }, { "$addToSet": { "properties.players": "Mark" }}, )
  • @AnthonyWinzlet 我试过了。但同样的结果。 {"$addToSet":{"properties.players":"Mark"}} 对象被添加到玩家字段,而不是添加到列表中。在此操作之后,我也对数据类型如何从数组切换到对象感到困惑。

标签: node.js mongodb mongodb-query loopbackjs


【解决方案1】:

您应该扩展模型功能以使用这些运算符。 比如:

"options": {    
    "mongodb": {
      "collection": "model_collection",
      "allowExtendedOperators": true
    }
  },

如环回文档中所述:https://loopback.io/doc/en/lb2/MongoDB-connector.html

然后你可以像这样使用它:

team.update({teamID:'teams32'},{ $addToSet:{ players: 'Mark'}},
     function(err,data){
         console.log(err,data,'result');
      });

【讨论】:

  • 我猜环回不支持通过SDK在客户端的addToSet
【解决方案2】:

这值得两次调用,但可能会对您有所帮助:

team.addPlayer = function (player, cb) {
    team.findOne({where: {teamID: "teams32"}}, function (err, team) {
        if (!err && team) {
            var players = [];
            if (team.players) {
                players = team.players;
            }
            players.push(player);
            team.updateAttributes({players: players}, function(err, team) {
                cb (err, team);
            });
        } else {
            cb (err, {});
        }
    });
};

team.remoteMethod('addPlayer', {
    accepts: {arg: 'player', type: 'string', required: true},
    returns: {arg: 'team', type: 'object'},
    http: {verb: 'put'}
});

【讨论】:

  • 这是一个很好的答案。我决定采用这种方法,因为我找不到任何其他方法。但这涉及两次查询数据库。我更愿意使用单个查询来减少在应用程序级别上完成的工作量并减少查询的数量。环回不可能吗?
  • 我同意,但我没有看到任何其他内容。您是否尝试过@Anthony Winzlet 在他的评论中提出的建议?
  • 是的,我也试过了。但对我没有用。这很有趣,因为我在 ExpressJS 上成功地使用了 $push 和 $addToSet 和 Mongoose。但它根本不适用于 Loopback。
【解决方案3】:

据我所知,环回中的查找、更新和任何其他功能与 MongoDB 原生查询不同。它有自己的定制。所以 team.updatedb.team.update() 不同。 因此,您可以使用上一个答案中所述的 2 个 db 查询,也可以尝试通过获取 datasource 来运行本机查询。然后您可以轻松使用 $addToSet,它会一键完成。

team.getDataSource().connector.connect(function (err, db) {
    var collection = db.collection("team");
    collection.update(filter,{$addToSet: {players:{$addToSet:{'Mark'}}}}, function(err,res){ /*Anything you want to do here*/ })
})

这可能会有所帮助。

【讨论】:

    【解决方案4】:

    我刚刚使用 node --version v10.16.0 和 loopback@3.26.0 实现了这个端点

    有了它,我可以将值附加到模型中的任何字段(目前仅处理数组类型字段)。数据参数应类似于 [ "one", 2, true ]

        Dataset.appendToArrayField = function (id, fieldName, data, ctx, next) {
        const where = {pid: id};
        var $addToSet = {};
        // $each is necessary as data is an array of values
        // $addToSetis necessary to append to the field and not overwrite
        $addToSet[fieldName] = { $each: data };
        Dataset.update(where,  { $addToSet });
        next();
    };
    
    Dataset.remoteMethod("appendToArrayField", {
        accepts: [{
                arg: "id",
                type: "string",
                required: true,
                description: ""
            },
            {
                arg: "fieldName",
                type: "string",
                required: true,
                description: "Name of field to append data to"
            },
            {
                arg: "data",
                type: "array",
                required: true,
                description: "An array of values to append"
            },
            {
                arg: 'options',
                type: 'object',
                http: {
                    source: 'context'
                }
            }
        ],
        http: {
            path: "/appendToArrayField",
            verb: "post"
        },
        returns: {
            type: "Object",
            root: true
        },
        description: "updates a single record by appending data to the specified field"
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-17
      • 2017-08-31
      • 1970-01-01
      • 2021-02-19
      • 1970-01-01
      相关资源
      最近更新 更多