【问题标题】:MongoDB aggregation, nodejs generate dynamic query with AND & ORMongoDB聚合,nodejs用AND & OR生成动态查询
【发布时间】:2022-01-20 23:37:48
【问题描述】:

我的 nodejs 代码中有 MongoDB 的聚合查询。

const query = {
  '$expr':{
    '$and':[
      {'$eq': ['$appId', req.user.appId]},
    ]
  }
}

从前端收到一个过滤器对象,如下:

{
  shops: '604c776763c302032e610347',
  offset: '0',
  limit: '20',
}

我需要在查询中动态推送商店 ID。需要是 appId -> user.appID AND targetFrom || targetTo 来自过滤器对象)

shops 可以是一个 idid 数组,为此我使用$in 运算符

query['$expr']['$and'].push({
  $eq: [
    {
      $or: [
        {"targetFrom": {$in: bb}},
        {"targetTo": {$in: bb}}
      ]
    }
  ]
})

旧版代码如下:

const query = {
  $and: [
    {appId: req.user.appId}
  ]
}

query['$and'].push({
  $or: [
    {"targetFrom": {$in: bb}}, <- in bb is mongodb objectID
    {"targetTo": {$in: bb}}
  ]
})

更新

如何在我的 items 对象数组中按 ID 搜索一些 item

if(req.query.products) {
  typeof req.query.products === 'string' ? req.query.products = [req.query.products] : req.query.products
  let bb = req.query.products.map(function(el) { return mongoose.Types.ObjectId(el) })
  query['$expr']['$and'].push({
    $and: [
      {
        items: {
          $in: ['item.itemId', bb]
        }
       }
     ]
   })
}

【问题讨论】:

    标签: node.js typescript mongodb express mongoose


    【解决方案1】:

    请查看以下是否满足您的要求:

    Mongoplayground link

    假设:

    1. req.user.appId 是一个字符串。
    2. bb 是一个由 objectId 或字符串组成的数组([ObjectId("asdfsd"),ObjectId("badsfds")] 等)
    const query = {
      "$expr": {
          $and: [{
            "$eq": ["$appId",req.user.appId],
          }]
          
      }
    }
    
    query['$expr']['$and'].push({
      $or: [
        {
          $in: [
            "$targetFrom",
            bb
          ]
        },
        {
          $in: [
            "$targetTo",
            bb
          ]
        }
      ]
    })
    

    编辑:要求已更新:获取具有特定appId 的所有对象,其中targetFromtargetTo 是给定数组之一,date 介于给定startDateendDate 之间:

    Monogplayground

    在上面的 mongoplayground 中,我正在获取 appId 为“1”、startDate2022-01-01endDate2022-01-31 且 bb 为 ["a","c" 的所有对象,“X”]。这应该获取所有 3 个文档,但日期会过滤掉第三个文档,因为该文档中的 date2021-12-24。如果您在此之前更改日期,您将获得全部 3 个。

    const query = {
      "$expr": {
          $and: [{
            "$eq": ["$appId",req.user.appId],
          }]
    
      }
    }
    
    query['$expr']['$and'] = query['$expr']['$and'].concat([{
              $and: [
                {
                  $gte: [
                    "$date",
                    startDate
                  ]
                },
                {
                  $lt: [
                    "$date",
                    endDate
                  ]
                }
              ]
            },{
      $or: [
        {
          $in: [
            "$targetFrom",
            bb
          ]
        },
        {
          $in: [
            "$targetTo",
            bb
          ]
        }
      ]
    }])
    

    编辑:要求更新:需要添加items.id过滤器。

    Mongoplayground Link

    如果您想在items 中没有对象具有给定ID 的情况下过滤掉文档,只需将我在$and 数组中添加的额外对象添加到$match stage

    {
     $in: [
           1,
           "$items.id",
     ]
    }
    

    如果您不想过滤掉此类文档,但想过滤掉 items 中的所有对象,其中 items.id 不是给定的 ID,我能找到的唯一解决方案是使用 $project 阶段,添加到新的 mongoplayground 链接中。

    【讨论】:

    • 也许你能帮我解决这个问题?) query.date = { $gte: startDate, $lt: endDate } query['$and'].push({ $or: [ {"日期": {$gte: startDate, $lt: endDate}}, ] })
    • 在您的数据库中,date 是字符串 (ISOdateString) 还是日期对象?
    • 它是 ISOdateString
    • 什么是ISOdateString?要么是 Date 对象(MongoDB 提供了一个名为 ISODate 的别名),要么是 String - 没有别的。
    • @WernfriedDomscheit wiki MDN
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 1970-01-01
    • 2020-02-12
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    • 2014-02-14
    相关资源
    最近更新 更多