Mongoose:在数组中查找标签并返回匹配的文档

时间:2016-08-06 09:33:26

标签: mongodb mongoose

在我目前的Mongo DB中,我有一个简单的Parts集合,其中包含Parent Children关系,如下所示:

{"partcode": "Parent1","children": ["Child1","Child2","Child3"]}

{"partcode": "Child1","label": ["label1"]}
{"partcode": "Child2","label": ["label1"]}
{"partcode": "Child3","label": ["label1"]}

为了返回零件代码的子代,我使用以下Mongoose函数:

PartSchema.static('getChildren', function(query, callback) {
  var self = this,
  self.findOne(query, {children: 1, _id: 0})
    .exec(function(err, doc) {
      return (self.find({
        "partcode": {
          "$in": doc.children
        }
      }, {_id: 0}, callback));
    });
});

返回以下数组:

[{"partcode": "Child1","label": ["label1"]},
{"partcode": "Child2","label": ["label1"]},
{"partcode": "Child3","label": ["label1"]}]

我想实现一个标签系统,我可以将标签指定为元子,并让代码返回与该标签匹配的所有子标签。

{"partcode": "Parent1","children": ["*label1"]}

将返回:

[{"partcode": "Child1","label": ["label1"]},
{"partcode": "Child2","label": ["label1"]},
{"partcode": "Child3","label": ["label1"]}]

我将在父文档的子字段中指定一个标签,作为一个特殊字符开头(目前,我正在使用' *',但很乐意改变如果需要,那就是其他东西。)

伪代码:

  1. 找到
  2. 获取家长 孩子阵列
  3. 在数组中,如果 child label 字符开头
    1. 获取与标签
    2. 匹配的所有部件代码的数组
    3. 数组
    4. 中替换标签的代码
  4. 返回儿童数组
  5. 也不应该退回没有标签字符的儿童。

2 个答案:

答案 0 :(得分:1)

我按照以下方式工作:

PartSchema.static('getChildren', function(query, callback) {
  var self = this,
    children = [],
    labels = [];
  self.findOne(query, {children: 1, _id: 0})
    .exec(function(err, doc) {
      //find labels
      labels = _.filter(doc.children, obj => /^\*/.test(obj));
      //remove labels from children array
      children = _.difference(doc.children, labels);
      //remove label identifier '*'
      labels = _.map(labels, label => label.substring(1));
      self.find({
        vendor: vendor,
        $or: [{
          "partcode": {
            "$in": children
          }
        }, {
          "label": {
            "$in": labels
          }
        }]
      }, {_id: 0}, callback);
    });
});

我对评论很感兴趣。特别是在优雅,结构,惯例等方面。任何形状或丑陋的东西都会让你眼前一亮?

答案 1 :(得分:0)

跟进OP's self answer

此处您不需要特殊字符(*)来区分标签和子字段。这也会减少您使用的数组操作(filterdifferencemap)。

因此,假设您没有标签的特殊字符,您的收藏将如下所示:

{"partcode": "Parent1","children": ["label1"]}

[{"partcode": "Child1","label": ["label1"]},
{"partcode": "Child2","label": ["label1"]},
{"partcode": "Child3","label": ["label1"]}]

以下代码将为您提供所需的结果:

PartSchema.static('getChildren', function(query, callback) {
  var self = this,
    children = [],
    labels = [];
  self.findOne(query, {children: 1, _id: 0})
    .exec(function(err, doc) {
// simply find for children in both `label` and `partcode` fields,
// using whole children array
          self.find({
            vendor: vendor,
            $or: [{
              "partcode": {
                "$in": doc.children
              }
            }, {
              "label": {
                "$in": doc.children
              }
            }]
          }, {_id: 0}, callback);
        });
    });

注意:如果child中的doc字段不是另一个label中的doc字段,则此解决方案适用,反之亦然。