Avoiding Cursor Invalidity Caused by hideIndex
Scenarios
In DDS, some operations may cause cursors to be invalid. The behaviors of DDS are the same as those of MongoDB Community Edition. The following are some common examples:
Invalid cursors caused by hideIndex
Cause:
The hideIndex operation changes the metadata of an index, invalidating the existing cursor.
Sample code:
(function() { "use strict"; let collName = "test_coll"; let coll = db.getCollection(collName); coll.drop(); // Create an index and insert data. coll.createIndex({x: 1}, {background: false}); for (var i = 0; i < 1000; ++i) { coll.insert({x: i}); } // Obtain a cursor. let cursor = coll.find({x: {$gte: 1}}); // Use the cursor, but the cursor is not exhausted. for (var i = 0; i < 101; ++i) { let doc = cursor.next(); print(tojson(doc)); } // Hide an index before the cursor is exhausted. coll.hideIndex("x_1"); // Traverse the cursor. cursor.forEach((doc) => { // An error is reported for the cursor. // "errmsg" : "definition of index 'x_1' changed" // "codeName" : "QueryPlanKilled" print(tojson(doc)); }); })();
Result:
The cursor is invalid. Errors may be reported.
2024-12-24T16:26:42.445+0800 E QUERY [js] Error: getMore command failed: { "ok" : 0, "errmsg" : "definition of index 'x_1' changed", "code" : 175, "codeName" : "QueryPlanKilled" } :
Invalid cursors caused by dropIndex
Cause:
After an index is deleted, DDS needs to recalculate query plans, invalidating the existing cursor.
Sample code:
(function() { "use strict"; let collName = "test_coll"; let coll = db.getCollection(collName); coll.drop(); // Create an index and insert data. coll.createIndex({x: 1}, {background: false}); for (var i = 0; i < 1000; ++i) { coll.insert({x: i}); } // Obtain a cursor. let cursor = coll.find({x: {$gte: 1}}); // Use the cursor, but the cursor is not exhausted. for (var i = 0; i < 101; ++i) { let doc = cursor.next(); print(tojson(doc)); } // Delete an index before the cursor is exhausted. coll.dropIndex("x_1"); // Traverse the cursor. cursor.forEach((doc) => { // An error is reported for the cursor. // "errmsg" : "index 'x_1' dropped", // "codeName" : "QueryPlanKilled" print(tojson(doc)); }); })();
Result:
The cursor is invalid because query plans need to be recalculated after an index is deleted.
2024-12-25T10:34:29.948+0800 E QUERY [js] Error: getMore command failed: { "ok" : 0, "errmsg" : "index 'x_1' dropped", "code" : 175, "codeName" : "QueryPlanKilled" }
Invalid cursors caused by renameCollection
Cause:
The renameCollection operation also causes cursors to become invalid.
Sample code:
(function() { "use strict"; let collName = "test_coll"; let coll = db.getCollection(collName); coll.drop(); // Create an index and insert data. coll.createIndex({x: 1}, {background: false}); for (var i = 0; i < 1000; ++i) { coll.insert({x: i}); } // Obtain a cursor. let cursor = coll.find({x: {$gte: 1}}); // Use the cursor, but the cursor is not exhausted. for (var i = 0; i < 101; ++i) { let doc = cursor.next(); print(tojson(doc)); } // Rename a collection before the cursor is exhausted. coll.renameCollection("test_coll_reaname"); // Traverse the cursor. cursor.forEach((doc) => { // An error is reported for the cursor. // "errmsg" : "collection dropped between getMore calls", // "codeName" : "OperationFailed" print(tojson(doc)); }); })();
Result:
The cursor is invalid because the name of the collection is changed and the cursor loses the context.
2024-12-25T10:39:28.624+0800 E QUERY [js] Error: getMore command failed: { "ok" : 0, "errmsg" : "collection dropped between getMore calls", "code" : 96, "codeName" : "OperationFailed" } :
Invalid cursors caused by dropCollection
Cause:
Deleting a collection causes cursors to lose the context. As a result, cursors become invalid.
Sample code:
(function() { "use strict"; let collName = "test_coll"; let coll = db.getCollection(collName); coll.drop(); // Create an index and insert data. coll.createIndex({x: 1}, {background: false}); for (var i = 0; i < 1000; ++i) { coll.insert({x: i}); } // Obtain a cursor. let cursor = coll.find({x: {$gte: 1}}); // Use the cursor, but the cursor is not exhausted. for (var i = 0; i < 101; ++i) { let doc = cursor.next(); print(tojson(doc)); } // Delete a collection before the cursor is exhausted. coll.drop(); // Traverse the cursor. cursor.forEach((doc) => { // An error is reported for the cursor. // "errmsg" : "collection dropped between getMore calls", // "codeName" : "OperationFailed" print(tojson(doc)); }); })();
Result:
The cursor is invalid because the collection is deleted and the cursor loses the context.
2024-12-25T10:40:33.737+0800 E QUERY [js] Error: getMore command failed: { "ok" : 0, "errmsg" : "collection dropped between getMore calls", "code" : 96, "codeName" : "OperationFailed" } :
Solution
- Process cursors before an index operation: Ensure that a cursor is exhausted before the hideIndex or dropIndex operation.
- Re-obtain cursors: If an index changes, perform the query operation again to obtain the new cursor.
- Plan in advance: Do not perform index operations during long-time queries.
Sample code:
(function() { "use strict"; let collName = "test_coll"; let coll = db.getCollection(collName); coll.drop(); // Create an index and insert data. coll.createIndex({x: 1}, {background: false}); for (var i = 0; i < 1000; ++i) { coll.insert({x: i}); } // Obtain a cursor. let cursor = coll.find({x: {$gte: 1}}); // Use the cursor, but the cursor is not exhausted. for (var i = 0; i < 101; ++i) { let doc = cursor.next(); print(tojson(doc)); } // Hide an index before the cursor is exhausted. coll.hideIndex("x_1"); // Traverse the cursor. // cursor.forEach((doc) => { // An error is reported for the cursor. // "errmsg" : "definition of index 'x_1' changed" // "codeName" : "QueryPlanKilled" // print(tojson(doc)); // }); // Obtain the cursor again. cursor = coll.find({x: {$gte: 1}}); cursor.forEach((doc) => { print(tojson(doc)); }); })();
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
For any further questions, feel free to contact us through the chatbot.
Chatbot