【问题标题】:Filter to not Include Matched Values in Result Arrays过滤以不包括结果数组中的匹配值
【发布时间】:2018-03-01 05:05:25
【问题描述】:

我有一个查询,我首先要匹配找到匹配用户的列表,然后从传入的外部用户数组中过滤掉匹配项,这样我就得到了尚未匹配的用户 ID。

这是一个匹配模式:

const mongoose = require('mongoose'); // only match two users at a time.
const Schema = mongoose.Schema;

const MatchSchema = new Schema({
    participants: [{
        type: String, ref: 'user'        
    }],
    blocked: {
        type: Boolean,
        default: false
    }
});

这是带有解释的查询:

db.getCollection('match').aggregate([
               { 
          '$match': {
               '$and': [       
                    { participants: "599f14855e9fcf95d0fe11a7" }, // the current user.
                    { participants: {'$in': [ "598461fcda5afa9e0d2a8a64","598461fcda5afa9e0d111111", "599f14855e9fcf95d0fe5555"] } } // array of external users that I want to check if the current user is matched with.
                ]
            }
        },
        {
            '$project': {
                'participants': 1
            }
        },

这将返回以下结果:

{
    "_id" : ObjectId("59c0d76e66dd407f5efe7112"),
    "participants" : [ 
        "599f14855e9fcf95d0fe11a7", 
        "599f14855e9fcf95d0fe5555"
    ]
},
{
    "_id" : ObjectId("59c0d76e66dd407f5efe75ac"),
    "participants" : [ 
        "598461fcda5afa9e0d2a8a64", 
        "599f14855e9fcf95d0fe11a7"
    ]
}

接下来我想做的是将参与者数组从两个结果合并到一个数组中。

然后我想从外部用户数组中取出那些匹配的项目,这样我就剩下尚未匹配的用户 ID。

任何帮助将不胜感激!

【问题讨论】:

  • 给定您问题中的行,这可能不是最好的示例数据集:“然后我想从外部用户数组中删除那些匹配的项目,这样我就剩下尚未匹配的用户 ID。”。那么你到底是什么意思呢?这是否意味着您期望从与查询匹配的文档中获得参与者的“唯一列表”,其中“其中不是查询本身提供的参数之一”?因此,您提供要匹配的值列表,然后您希望返回的每个值除了那些提供的值?
  • 基本上我想做的是1:传入一个可能与当前用户匹配或不匹配的用户数组(数组X)。 2:查找匹配用户列表。 3:从(数组X)中删除匹配的用户列表。 4:返回未匹配的唯一用户列表。

标签: javascript mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

如果您不希望这些结果出现在数组中,那么$filter 将它们取出。

通过使用$or(聚合逻辑版本)构建条件:

var currentUser = "599f14855e9fcf95d0fe11a7",
    matchingUsers = [ 
      "598461fcda5afa9e0d2a8a64",
      "598461fcda5afa9e0d111111",
      "599f14855e9fcf95d0fe5555"
    ],
    combined = [currentUser, ...matchingUsers];

db.getCollection('match').aggregate([
  { '$match': {
    'participants': { '$eq': currentUser, '$in': matchingUsers }
  }},
  { '$project': {
    'participants': {
      '$filter': {
        'input': '$participants',
        'as': 'p',
        'cond': {
          '$not': {
            '$or': combined.map(c =>({ '$eq': [ c, '$$p' ] }))
          }
        }
      }
    }
  }}
])

如果您有支持它的 MongoDB 3.4,或者使用 $in(再次是聚合版本):

db.getCollection('match').aggregate([
  { '$match': {
    'participants': { '$eq': currentUser, '$in': matchingUsers }
  }},
  { '$project': {
    'participants': {
      '$filter': {
        'input': '$participants',
        'as': 'p',
        'cond': {
          '$not': {
            '$in': ['$p', combined ]
          }
        }
      }
    }
  }}
])

真的没关系。这只是在发送管道之前使用 JavaScript 构建表达式或让支持的管道运算符在实际支持的地方进行数组比较的区别。

请注意,您还可以通过使用$and 的“隐式”形式更有效地编写$match,如图所示。

另请注意,您的架构定义存在问题(但与此特定查询无关)。您不能在另一个集合中将“引用”作为String 使用另一个集合,而在另一个集合中它将是ObjectId_id 的默认值,并假定获得的十六进制值)。这种不匹配意味着.populate()$lookup 函数无法工作。所以你真的应该更正类型。

与此无关。但是您需要优先解决一些问题。

【讨论】:

    猜你喜欢
    • 2021-06-18
    • 2015-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-11
    • 2016-05-28
    • 1970-01-01
    • 2015-01-01
    相关资源
    最近更新 更多