【问题标题】:Mongoose: Find label in array and return matching documentsMongoose:在数组中查找标签并返回匹配的文档
【发布时间】:2016-08-11 17:35:39
【问题描述】:

在我当前的 Mongo DB 中,我有一个简单的 Parts 集合,具有父子关系,如下所示:

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

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

为了返回一个partcode的孩子,我使用了下面的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. 获取Parent的children数组
  3. 在数组中,如果 child 以 label 字符开头
    1. 获取与 label 和
    2. 匹配的所有部件代码的数组
    3. 用部分代码替换 children 数组中的标签
  4. 返回儿童数组

还应返回未以标签字符开头的子代。

【问题讨论】:

  • 您可以在 $in 语句中使用正则表达式。类似于find({label: {$in: [/label1/]}}, callback) 的内容确保为label 字段添加索引
  • 谢谢。我对发现的细节没意见。我创建了一个标签函数,它返回具有特定标签的所有对象。我不确定如何最好地构建它;也就是大招。我倾向于使用聚合管道。

标签: mongodb mongoose


【解决方案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);
    });
});

我会对 cme​​ts 感兴趣。尤其是在优雅、结构、惯例等方面。任何如此糟糕的形式或丑陋的东西,都让你眼花缭乱?

【讨论】:

  • 你真的需要一个特殊的字符来区分吗?并应用过滤器和差异并使用地图..您可以通过删除特殊字符来使其更简单..
  • 发布了我自己的答案作为改进
【解决方案2】:

跟进OP's self answer,

这里不需要特殊字符 (*) 来区分标签和子字段。这也将减少您使用的数组操作(filter、difference、map)。

所以假设你没有标签的特殊字符,你的集合看起来像:

{"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);
        });
    });

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

【讨论】:

  • 嗨,Naeem,感谢您的回复。恐怕我们确实需要一个特殊字符来区分“标签”和“儿童”,因为部分代码可能与标签同名。
猜你喜欢
  • 2021-08-20
  • 2019-04-23
  • 1970-01-01
  • 2020-02-19
  • 2015-05-23
  • 2019-06-29
  • 1970-01-01
  • 2015-02-04
  • 2021-09-30
相关资源
最近更新 更多