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

6

在我的当前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"]}

would return:

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

我将在父文档的children字段中指定一个标签,以特殊字符开头(目前我正在使用'*',但如有需要,我可以更改为其他字符)。
伪代码:
1.查找Parent 2.获取children数组 3.在数组中,如果child字符开头:
- 获取与匹配的所有零件的partcodes数组 - 在children数组中用partcodes替换 4.返回children数组
不以标签字符开头的子元素也应被返回。

1
你可以在$in语句中使用正则表达式。类似于find({label: {$in: [/label1/]}}, callback)。确保为“label”字段添加索引。 - Andreas
谢谢。我对查找周围的细节感到满意。我创建了一个标签函数,返回具有特定标签的所有对象。我不确定最佳结构是什么,也就是说,大体上的轮廓。我倾向于使用聚合管道。 - Terry
2个回答

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

我很希望能听到您的评论。特别是关于优雅、结构、约定等方面的意见。有什么不好的形式或丑陋的东西,会让您的眼睛感到不适吗?


你真的需要一个特殊字符来区分吗?并且应用过滤器和差异,还可以使用映射。如果只是删除特殊字符,你可以使它更简单。 - Naeem Shaikh
发布了我自己的答案作为改进。 - Naeem Shaikh

0

跟进 OP的自我回答,

在这里,您不需要一个特殊字符(*)来区分标签和子字段。这也将减少您使用的数组操作(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,感谢您的回复。恐怕我们确实需要一个特殊字符来区分“标签”和“子级”,因为部件代码可能与标签具有相同的名称。 - Terry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接