Node.js mongoose中如何按模式属性过滤

Node.js mongoose中如何按模式属性过滤,node.js,mongodb,mongoose,mongodb-query,aggregation-framework,Node.js,Mongodb,Mongoose,Mongodb Query,Aggregation Framework,我有一个组对象,它包含一个成员属性。members属性是一个对象数组。该对象具有以下属性 {"id" : "1", "status" : 1} 我的要求是获取给定组对象的状态为1的用户列表(通过给定id) 通过一个简单的get by ID查询和一个foreach,就可以做到这一点。但我想知道,是否有任何预先查询可以做到这一点 我的团队目标如下 var UserSchema = new Schema({ user_id:{ type : Schema.ObjectId, re

我有一个
对象,它包含一个
成员
属性。
members
属性是一个对象数组。该对象具有以下属性

{"id" : "1", "status" : 1}
我的要求是获取给定
对象的状态为
1
的用户列表(通过给定id)

通过一个简单的get by ID查询和一个
foreach
,就可以做到这一点。但我想知道,是否有任何预先查询可以做到这一点

我的团队目标如下

var UserSchema = new Schema({
  user_id:{
    type : Schema.ObjectId,
    ref : 'User',
    default : null
  },
  status:{
    type : Number,
    default : null /* 1 - pending | 2 - rejected | 3 - accepted*/
  },
});

var GroupSchema = new Schema({
  type:{
    type : Number,
    default : 1 /* 1 - group | 2 - community*/
  },
  name:{
    type:String,
    default:null
  },
  members:[UserSchema]

},{collection:"groups"});

提前谢谢。

假设您的收藏名称为
,您可以这样查询:

db.groups.find({"members.status":1}, {"members":1});
这将获取状态为1的所有用户。如果要基于特定的用户id(此处假设用户id为“1A”)进行查询,可以添加如下对象:

db.groups.find({"members.status":1, "members.user_id":"1A"}, {"members":1});

您可以使用聚合框架根据给定的组id和成员数组状态字段筛选groups集合中的文档。这将是您的初始管道阶段,由操作员驱动

下一个管道步骤应该是操作符,它根据给定条件选择成员数组的子集。这是必要的,因为之前的管道仅在文档级别进行过滤,而不是在数组/字段级别进行过滤

获得过滤后的数组后,可以应用函数作为“填充”成员列表的方法。但是,由于
localField
是一个数组,您希望将其中的元素与
foreignField
进行匹配,后者是单个元素,因此在应用操作符之前,您需要将数组作为聚合管道的一个阶段进行匹配

以下示例演示如何在您的案例中应用上述所有步骤:

Group.aggregate([
    { 
        "$match": { 
            "_id": groupId,
            "members.status": 1         
        } 
    },
    {
        "$filter": {
            "input": "$members",
            "as": "member",
            "cond": { "$eq": ["$$member.status", 1] }
        }
    }
    { "$unwind": "$members" },
    {
        "$lookup": {
            "from": "users"
            "localField": "members.user_id",
            "foreignField": "_id",
            "as": "member"
        }
    }
]).exec(function(err, results) { 
    if (err) throw err;
    console.log(results);
});
结果将包含同时具有组和用户属性的文档列表


如果您的MongoDB版本不支持版本3.2中引入的运算符。x和更新,然后考虑使用<强> < /强>和<强> < /强>运算符组合来过滤<强> <强>管道中的数组元素。 操作符本质上创建了一个新的数组字段,该字段保存数组中每个元素的子表达式中计算逻辑的结果值。然后,运算符返回一个集合,其中的元素出现在第一个集合中,但不出现在第二个集合中;i、 e.执行第二组相对于第一组的相对补码。在这种情况下,它将通过
status
属性返回最终成员数组,该数组包含与父文档不相关的元素

管道步骤之后执行聚合操作,由于返回的文档是纯javascript对象,而不是(可以返回任何形状的文档),因此需要将结果强制转换为,以便在字段上使用填充函数来填充结果

以下示例演示了上述解决方法:

Group.aggregate([
    { 
        "$match": { 
            "_id": groupId,
            "members.status": 1         
        } 
    },
    {
        "$project": {
            "type": 1, "name": 1,
            "members": {
                "$setDifference": [
                    {
                        "$map": {
                            "input": "$members",
                            "as": "member",
                            "in": {
                                "$cond": [
                                    { "$eq": [ "$$member.status", 1 ] },
                                    "$$member",
                                    false
                                ]
                            }
                        }
                    },
                    [false]
                ]
            }
        }
    }
]).exec(function(err, result) { 
    if (err) throw err;
    var docs = result.map(function(doc) { return new Group(doc) });
    Group.populate(docs, { "path": "members" }, function(err, results) {
        if (err) throw err;
        console.log(JSON.stringify(results, undefined, 4 ));
        res.json(results);
    });
});

您是指一个给定的组对象而不是post对象吗?与其给出架构定义,不如共享一些示例文档和预期的输出,这样就可以很容易地理解您要完成的任务。@chridam
group
object。编辑了该问题。@suzo我的预期结果是一组状态为1的成员。您能检查我的答案并告诉我这是否是您所期望的吗?@sacDahal它的工作原理是对同一数据库中的未归档集合执行“左外部联接”,以筛选“联接”集合中的文档进行处理。
$lookup
阶段在输入文档中的字段与“联接”集合中的文档中的字段之间进行相等匹配。有时,
$lookup
可能被错误地用于将MongoDB视为关系数据库,但开发人员应该知道何时使用它是合适的,何时它是反模式的。看起来我的MongoDB版本与
$filter
管道阶段不兼容。有没有其他可能的阶段可以用来替换
$filter
。你的MongoDB和Mongoose版本是什么?@ErangaKapukotuwa我已经添加了一个解决方案,试试看,如果可行的话请告诉我。