You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MongoDB动态数组字段排序及存储过程实现咨询

Hey there! Let's break down how to add sorting to your MongoDB query and address your question about stored procedures/functions.

Adding Sorting by the Target Datetime Field

Since your target datetime is nested inside an array of objects, we can't use a simple field path in sort() directly. Instead, we have two reliable approaches depending on your MongoDB version:

Option 1: Use the Aggregation Pipeline (Works in All Supported Versions)

This approach lets you explicitly extract the datetime value first, then sort and paginate. Here's how to refactor your query:

db.getCollection('Collection').aggregate([
  // Match your original filter criteria
  {
    $match: {
      FieldsDatas: {
        $elemMatch: {
          FieldId: '955c9843-1535-4df8-a1c4-09430ac9f6ba',
          Value: { $ne: ["Contact"] }
        }
      }
    }
  },
  // Add a temporary field with the parsed datetime for sorting
  {
    $addFields: {
      sortDate: {
        $dateFromString: {
          dateString: {
            // Extract the Value array's first element from the matching FieldId object
            $arrayElemAt: [
              {
                $arrayElemAt: [
                  {
                    $filter: {
                      input: "$FieldsDatas",
                      cond: { $eq: ["$$this.FieldId", "15355b82-4fae-4c09-acb4-13f95e8c2d4e"] }
                    }
                  }.Value,
                  0 // Get the first (and only) Value array entry
                ]
              },
              0 // Get the first matching FieldsDatas object
            ]
          }
        }
      }
    }
  },
  // Sort by the parsed datetime (use -1 for descending order)
  { $sort: { sortDate: 1 } },
  // Apply pagination
  { $skip: 30 },
  { $limit: 5 },
  // Optional: Remove the temporary sortDate field from results
  { $project: { sortDate: 0 } }
])

Option 2: Use Aggregation Expressions in sort() (MongoDB 4.4+)

If you're running MongoDB 4.4 or later, you can use aggregation expressions directly in the sort() method of a find() query, avoiding the full pipeline:

db.getCollection('Collection').find({
  "$and": [{
    FieldsDatas: {
      $elemMatch: {
        FieldId: '955c9843-1535-4df8-a1c4-09430ac9f6ba',
        Value: { $ne: ["Contact"] }
      }
    }
  }]
})
.sort({
  // Parse and extract the target datetime directly in the sort clause
  $dateFromString: {
    dateString: {
      $arrayElemAt: [
        {
          $arrayElemAt: [
            {
              $filter: {
                input: "$FieldsDatas",
                cond: { $eq: ["$$this.FieldId", "15355b82-4fae-4c09-acb4-13f95e8c2d4e"] }
              }
            }.Value,
            0
          ]
        },
        0
      ]
    }
  }: 1 // 1 for ascending, -1 for descending
})
.skip(30)
.limit(5)

Can This Be Implemented with Stored Procedures/Functions?

Absolutely, though it's not strictly necessary unless you need to reuse this logic frequently across multiple clients. MongoDB lets you store JavaScript functions in the db.system.js collection for reuse:

Example Stored Function

// Save the function to the database
db.system.js.save({
  _id: "getSortedFormEntries",
  value: function(skipAmount, limitAmount) {
    return db.getCollection('Collection').aggregate([
      { $match: {
          FieldsDatas: {
            $elemMatch: {
              FieldId: '955c9843-1535-4df8-a1c4-09430ac9f6ba',
              Value: { $ne: ["Contact"] }
            }
          }
        }
      },
      { $addFields: {
          sortDate: {
            $dateFromString: {
              dateString: {
                $arrayElemAt: [
                  { $arrayElemAt: [
                    { $filter: {
                        input: "$FieldsDatas",
                        cond: { $eq: ["$$this.FieldId", "15355b82-4fae-4c09-acb4-13f95e8c2d4e"] }
                    } }.Value,
                    0
                  ] },
                  0
                ]
              }
            }
          }
        }
      },
      { $sort: { sortDate: 1 } },
      { $skip: skipAmount },
      { $limit: limitAmount },
      { $project: { sortDate: 0 } }
    ]).toArray();
  }
});

// Call the function later
db.getSortedFormEntries(30, 5);

A quick note: While stored functions work, many developers prefer encapsulating this logic in their application code instead—it's easier to maintain, debug, and version control.

内容的提问来源于stack exchange,提问作者Mani J

火山引擎 最新活动