jstests/core/timeseries/libs/timeseries_lastpoint_helpers.js
/**
    Test cases:
     1. Lastpoint queries on indexes with descending time and $first/$top (DISTINCT_SCAN).
     2. Lastpoint queries on indexes with ascending time and $last/$bottom (no DISTINCT_SCAN).
     3. Lastpoint queries on indexes with ascending time and $last/$bottom and an additional
   secondary index so that we can use the DISTINCT_SCAN optimization.
*/
Test cases:
1. Lastpoint queries on indexes with descending time and $first/$top (DISTINCT_SCAN).
2. Lastpoint queries on indexes with ascending time and $last/$bottom (no DISTINCT_SCAN).
3. Lastpoint queries on indexes with ascending time and $last/$bottom and an additional
secondary index so that we can use the DISTINCT_SCAN optimization.
Test cases : 1 . Lastpoint queries on indexes with descending time and $first / $top ( DISTINCT_SCAN ) . 2 . Lastpoint queries on indexes with ascending time and $last / $bottom ( no DISTINCT_SCAN ) . 3 . Lastpoint queries on indexes with ascending time and $last / $bottom and an additional secondary index so that we can use the DISTINCT_SCAN optimization .
function testAllTimeMetaDirections(tsColl, observerColl, getTestCases) {
    const testDB = TimeseriesAggTests.getTestDb();
    const testCases = [
        {time: -1, useBucketsIndex: false},
        {time: 1, useBucketsIndex: false},
        {time: 1, useBucketsIndex: true}
    ];
    for (const {time, useBucketsIndex} of testCases) {
        const isTimeDescending = time < 0;
        const canUseDistinct = isTimeDescending || useBucketsIndex;
        for (const metaDir of [1, -1]) {
            const index = {"tags.hostid": metaDir, time};
            const bucketsIndex = useBucketsIndex
                ? {"meta.hostid": metaDir, "control.max.time": 1, "control.min.time": 1}
                : undefined;
            const tests = getTestCases({
                canUseDistinct,
                canSortOnTimeUseDistinct: (metaDir > 0) && (isTimeDescending || useBucketsIndex),
                time,
                index
            });
            for (const {pipeline, expectStageNoIndex, precedingFilter} of tests) {
                const expectStage = expectStageNoIndex || expectCollScan;
                verifyLastpoint({tsColl, observerColl, pipeline, precedingFilter, expectStage});
            }
            const ixName = "tsIndex_time_" + time + "_meta_" + metaDir;
            tsColl.createIndex(index, {name: ixName});
            const bucketsColl = testDB["system.buckets.in"];
            const bucketsIxName = "bucketsIndex_time_" + time + "_meta_" + metaDir;
            if (bucketsIndex) {
                bucketsColl.createIndex(bucketsIndex, {name: bucketsIxName});
            }
            for (const {pipeline, expectStageWithIndex, precedingFilter} of tests) {
                verifyLastpoint({
                    tsColl,
                    observerColl,
                    pipeline,
                    precedingFilter,
                    expectStage: expectStageWithIndex
                });
            }
            tsColl.dropIndex(ixName);
            if (bucketsIndex) {
                bucketsColl.dropIndex(bucketsIxName);
            }
        }
    }
    tsColl.drop();
    observerColl.drop();
}
function testAllTimeMetaDirections ( tsColl , observerColl , getTestCases ) { const testDB = TimeseriesAggTests . getTestDb ( ) ; const testCases = [ { time : - 1 , useBucketsIndex : false } , { time : 1 , useBucketsIndex : false } , { time : 1 , useBucketsIndex : true } ] ; for ( const { time , useBucketsIndex } of testCases ) { const isTimeDescending = time < 0 ; const canUseDistinct = isTimeDescending || useBucketsIndex ; for ( const metaDir of [ 1 , - 1 ] ) { const index = { "tags.hostid" : metaDir , time } ; const bucketsIndex = useBucketsIndex ? { "meta.hostid" : metaDir , "control.max.time" : 1 , "control.min.time" : 1 } : undefined ; const tests = getTestCases ( { canUseDistinct , canSortOnTimeUseDistinct : ( metaDir > 0 ) && ( isTimeDescending || useBucketsIndex ) , time , index } ) ; for ( const { pipeline , expectStageNoIndex , precedingFilter } of tests ) { const expectStage = expectStageNoIndex || expectCollScan ; verifyLastpoint ( { tsColl , observerColl , pipeline , precedingFilter , expectStage } ) ; } const ixName = "tsIndex_time_" + time + "_meta_" + metaDir ; tsColl . createIndex ( index , { name : ixName } ) ; const bucketsColl = testDB [ "system.buckets.in" ] ; const bucketsIxName = "bucketsIndex_time_" + time + "_meta_" + metaDir ; if ( bucketsIndex ) { bucketsColl . createIndex ( bucketsIndex , { name : bucketsIxName } ) ; } for ( const { pipeline , expectStageWithIndex , precedingFilter } of tests ) { verifyLastpoint ( { tsColl , observerColl , pipeline , precedingFilter , expectStage : expectStageWithIndex } ) ; } tsColl . dropIndex ( ixName ) ; if ( bucketsIndex ) { bucketsColl . dropIndex ( bucketsIxName ) ; } } } tsColl . drop ( ) ; observerColl . drop ( ) ; }
Test cases:
1.
Test cases : 1 .
// Test both directions of the metaField sort for each direction of time. // Run all tests without an index. // Normally we expect to see a COLLSCAN with a SORT pushed into the cursor, but some // test-cases may override this. // Create index on the timeseries collection. // Create an additional secondary index directly on the buckets collection so that we // can test the DISTINCT_SCAN optimization when time is sorted in ascending order. // Re-run all tests with an index. // Drop indexes for next test. // Drop collections at the end of the test.