Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB 4.2中N个最新的按日重置单据新增字段_Mongodb_Mongodb Query_Aggregation Framework - Fatal编程技术网

MongoDB 4.2中N个最新的按日重置单据新增字段

MongoDB 4.2中N个最新的按日重置单据新增字段,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我收集了一系列与方案有关的文件: { _id: ObjectId, userId: ObjectId, marker: string, datetime: Date, etc... } 这是绑定到用户(userId)的标记(marker)的集合。绑定日期存储在datetime字段中 用户每天可以收到任意数量的标记 当我从这个集合中获取数据时,我需要添加一个名为allowed的额外字段,类型为boolean,只有当该记录位于用户日历日的N个最新记录中时,该字段才必须为true 例如,如果初始集合

我收集了一系列与方案有关的文件:

{ _id: ObjectId, userId: ObjectId, marker: string, datetime: Date, etc... }
这是绑定到用户(
userId
)的标记(
marker
)的集合。绑定日期存储在
datetime
字段中

用户每天可以收到任意数量的标记

当我从这个集合中获取数据时,我需要添加一个名为
allowed
的额外字段,类型为
boolean
,只有当该记录位于用户日历日的N个最新记录中时,该字段才必须为
true

例如,如果初始集合如下所示并且N==2

{_id: ..., userId: "a", marker: "m1", datetime: "2020-01-01.10:00"}
{_id: ..., userId: "a", marker: "m2", datetime: "2020-01-02.10:00"}
{_id: ..., userId: "a", marker: "m3", datetime: "2020-01-02.11:00"}
{_id: ..., userId: "a", marker: "m4", datetime: "2020-01-02.12:00"}
{_id: ..., userId: "a", marker: "m5", datetime: "2020-01-02.13:00"}
{_id: ..., userId: "b", marker: "m1", datetime: "2020-01-01.10:00"}
{_id: ..., userId: "b", marker: "m2", datetime: "2020-01-01.11:00"}
{_id: ..., userId: "b", marker: "m3", datetime: "2020-01-01.13:00"}
{_id: ..., userId: "b", marker: "m4", datetime: "2020-01-02.11:00"}
{_id: ..., userId: "b", marker: "m5", datetime: "2020-01-02.12:00"}
{_id: ..., userId: "b", marker: "m6", datetime: "2020-01-03.10:00"}
那么最终结果应该是这样的:

{_id: ..., userId: "a", marker: "m1", datetime: "2020-01-01.10:00", allowed: true}
{_id: ..., userId: "a", marker: "m2", datetime: "2020-01-02.10:00", allowed: true}
{_id: ..., userId: "a", marker: "m3", datetime: "2020-01-02.11:00", allowed: true}
{_id: ..., userId: "a", marker: "m4", datetime: "2020-01-02.12:00", allowed: false}
{_id: ..., userId: "a", marker: "m5", datetime: "2020-01-02.13:00", allowed: false}
{_id: ..., userId: "b", marker: "m1", datetime: "2020-01-01.10:00", allowed: true}
{_id: ..., userId: "b", marker: "m2", datetime: "2020-01-01.11:00", allowed: true}
{_id: ..., userId: "b", marker: "m3", datetime: "2020-01-01.13:00", allowed: false}
{_id: ..., userId: "b", marker: "m4", datetime: "2020-01-02.11:00", allowed: true}
{_id: ..., userId: "b", marker: "m5", datetime: "2020-01-02.12:00", allowed: true}
{_id: ..., userId: "b", marker: "m6", datetime: "2020-01-03.10:00", allowed: true}

我正在使用MongoDB 4.2

请尝试以下查询:

查询1:

 db.markers.aggregate([
    /** group docs based on userId & date(2020-01-01), push all matched docs to data */
    { $group: { _id: { userId: '$userId', datetime: { $arrayElemAt: [{ $split: ["$datetime", "."] }, 0] } }, data: { $push: '$$ROOT' } } },
    /** Re-forming data field with added new field allowed for only docs where criteria is met */
    {
        $addFields: {
            data: {
                $map:
                {
                    input: "$data",
                    as: "each",
                    /** conditional check to add new field on only docs which are 0 & 1 position of array */
                    in: { $cond: [{ $lte: [{ $indexOfArray: ["$data", '$$each'] }, 1] }, { $mergeObjects: ['$$each', { allowed: true }] }, { $mergeObjects: ['$$each', { allowed: false }] }] }
                }
            }
        }
    },
    /** unwind data */
    { $unwind: '$data' },
    /** making data object as root level doc */
    { $replaceRoot: { newRoot: "$data" } }])
db.markers.aggregate([
    { $group: { _id: { userId: '$userId', datetime: { $arrayElemAt: [{ $split: ["$datetime", "."] }, 0] } }, data: { $push: '$$ROOT' } } }, {
        $addFields: {
            data: {
                $map:
                {
                    input: "$data",
                    as: "each",
                    in: {
                        $cond: [{
                            $or: [{ $eq: [{ $arrayElemAt: ["$data", -1] }, '$$each'] }, { $eq: [{ $arrayElemAt: ["$data", -2] }, '$$each'] }]
                        },
                        { $mergeObjects: ['$$each', { allowed: true }] },
                        { $mergeObjects: ['$$each', { allowed: false }] }]
                    }
                }
            }
        }
    }, { $unwind: '$data' }, { $replaceRoot: { newRoot: "$data" } }])
查询2:

 db.markers.aggregate([
    /** group docs based on userId & date(2020-01-01), push all matched docs to data */
    { $group: { _id: { userId: '$userId', datetime: { $arrayElemAt: [{ $split: ["$datetime", "."] }, 0] } }, data: { $push: '$$ROOT' } } },
    /** Re-forming data field with added new field allowed for only docs where criteria is met */
    {
        $addFields: {
            data: {
                $map:
                {
                    input: "$data",
                    as: "each",
                    /** conditional check to add new field on only docs which are 0 & 1 position of array */
                    in: { $cond: [{ $lte: [{ $indexOfArray: ["$data", '$$each'] }, 1] }, { $mergeObjects: ['$$each', { allowed: true }] }, { $mergeObjects: ['$$each', { allowed: false }] }] }
                }
            }
        }
    },
    /** unwind data */
    { $unwind: '$data' },
    /** making data object as root level doc */
    { $replaceRoot: { newRoot: "$data" } }])
db.markers.aggregate([
    { $group: { _id: { userId: '$userId', datetime: { $arrayElemAt: [{ $split: ["$datetime", "."] }, 0] } }, data: { $push: '$$ROOT' } } }, {
        $addFields: {
            data: {
                $map:
                {
                    input: "$data",
                    as: "each",
                    in: {
                        $cond: [{
                            $or: [{ $eq: [{ $arrayElemAt: ["$data", -1] }, '$$each'] }, { $eq: [{ $arrayElemAt: ["$data", -2] }, '$$each'] }]
                        },
                        { $mergeObjects: ['$$each', { allowed: true }] },
                        { $mergeObjects: ['$$each', { allowed: false }] }]
                    }
                }
            }
        }
    }, { $unwind: '$data' }, { $replaceRoot: { newRoot: "$data" } }])
Query1将起作用并得到结果,但假设所给出的数据是样本数据&当您查看集合
用户ID:“a”时,标记:“m5”
将是第一个文档,就好像此集合具有连续的数据写入,那么最新文档将具有最新的
数据时间,因此Query1的索引0或1将不起作用,但在这里Query2将起作用。如果标记集合的有序数据与前面给出的完全相同,则可以使用Query1

注意:查询2中-我们可以使用与查询1相同的逻辑(即检查索引(0,1))而不是对象比较,但这仅适用于将
日期时间
字段的
$sort
作为第一阶段,我并没有走这条路线,因为在一个字段上对整个集合的数据进行排序不会比这更有效