diff --git a/mongoimport/mongoimport_test.go b/mongoimport/mongoimport_test.go index 7e072e7b3..9768667c0 100644 --- a/mongoimport/mongoimport_test.go +++ b/mongoimport/mongoimport_test.go @@ -1797,3 +1797,92 @@ func TestRoundTripViewExport(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, 4, n, "restored view should have correct number of rows") } + +// TestRoundTripFieldFile verifies that mongoexport --fieldFile limits exported +// fields, and that mongoimport correctly restores the filtered data. +func TestRoundTripFieldFile(t *testing.T) { + testtype.SkipUnlessTestType(t, testtype.IntegrationTestType) + + const dbName = "mongoimport_roundtrip_fieldfile_test" + + sessionProvider, _, err := testutil.GetBareSessionProvider() + require.NoError(t, err) + client, err := sessionProvider.GetSession() + require.NoError(t, err) + t.Cleanup(func() { + if err := client.Database(dbName).Drop(context.Background()); err != nil { + t.Errorf("dropping test database: %v", err) + } + }) + + db := client.Database(dbName) + _, err = db.Collection("source").InsertMany(t.Context(), []any{ + bson.D{{"a", int32(1)}}, + bson.D{{"a", int32(1)}, {"b", int32(1)}}, + bson.D{{"a", int32(1)}, {"b", int32(2)}, {"c", int32(3)}}, + }) + require.NoError(t, err) + + fieldFile, err := os.CreateTemp(t.TempDir(), "fields-*.txt") + require.NoError(t, err) + _, err = fieldFile.WriteString("a\nb\n") + require.NoError(t, err) + require.NoError(t, fieldFile.Close()) + + exportTarget, err := os.CreateTemp(t.TempDir(), "export-*.csv") + require.NoError(t, err) + require.NoError(t, exportTarget.Close()) + + exportToolOptions, err := testutil.GetToolOptions() + require.NoError(t, err) + exportToolOptions.Namespace = &options.Namespace{DB: dbName, Collection: "source"} + me, err := mongoexport.New(mongoexport.Options{ + ToolOptions: exportToolOptions, + OutputFormatOptions: &mongoexport.OutputFormatOptions{ + Type: "csv", + JSONFormat: "canonical", + FieldFile: fieldFile.Name(), + }, + InputOptions: &mongoexport.InputOptions{}, + }) + require.NoError(t, err) + defer me.Close() + + f, err := os.OpenFile(exportTarget.Name(), os.O_WRONLY, 0o644) + require.NoError(t, err) + _, err = me.Export(f) + require.NoError(t, err) + require.NoError(t, f.Close()) + + fields := "a,b,c" + importToolOptions, err := testutil.GetToolOptions() + require.NoError(t, err) + importToolOptions.Namespace = &options.Namespace{DB: dbName, Collection: "dest"} + mi, err := New(Options{ + ToolOptions: importToolOptions, + InputOptions: &InputOptions{ + File: exportTarget.Name(), + Type: "csv", + Fields: &fields, + ParseGrace: "stop", + }, + IngestOptions: &IngestOptions{}, + }) + require.NoError(t, err) + _, _, err = mi.ImportDocuments() + require.NoError(t, err) + + dest := db.Collection("dest") + n, err := dest.CountDocuments(t.Context(), bson.D{{"a", int32(1)}}) + require.NoError(t, err) + assert.EqualValues(t, 3, n, "3 documents should have a=1") + n, err = dest.CountDocuments(t.Context(), bson.D{{"b", int32(1)}}) + require.NoError(t, err) + assert.EqualValues(t, 1, n, "1 document should have b=1") + n, err = dest.CountDocuments(t.Context(), bson.D{{"b", int32(2)}}) + require.NoError(t, err) + assert.EqualValues(t, 1, n, "1 document should have b=2") + n, err = dest.CountDocuments(t.Context(), bson.D{{"c", int32(3)}}) + require.NoError(t, err) + assert.EqualValues(t, 0, n, "c=3 should not have been exported (not in fieldFile)") +} diff --git a/test/qa-tests/jstests/export/field_file.js b/test/qa-tests/jstests/export/field_file.js deleted file mode 100644 index e61394982..000000000 --- a/test/qa-tests/jstests/export/field_file.js +++ /dev/null @@ -1,60 +0,0 @@ -(function() { - - if (typeof getToolTest === "undefined") { - load('jstests/configs/plain_28.config.js'); - } - - // Tests running mongoexport exporting to csv using the --fieldFile option - jsTest.log('Testing exporting to csv using the --fieldFile option'); - - var toolTest = getToolTest('field_file'); - var commonToolArgs = getCommonToolArguments(); - - // the db and collections we'll use - var testDB = toolTest.db.getSiblingDB('test'); - var sourceColl = testDB.source; - var destColl = testDB.dest; - - // the export target - var exportTarget = 'jstests/export/testdata/field_file_export.csv'; - removeFile(exportTarget); - - // insert some data - sourceColl.insert({a: 1}); - sourceColl.insert({a: 1, b: 1}); - sourceColl.insert({a: 1, b: 2, c: 3}); - // sanity check the insertion worked - assert.eq(3, sourceColl.count()); - - // export the data, using a field file that specifies 'a' and 'b' - var ret = toolTest.runTool.apply(toolTest, ['export', - '--out', exportTarget, - '--db', 'test', - '--collection', 'source', - '--type=csv', - '--fieldFile', 'jstests/export/testdata/simple_field_file'] - .concat(commonToolArgs)); - assert.eq(0, ret); - - - // import the data into the destination collection - ret = toolTest.runTool.apply(toolTest, ['import', - '--file', exportTarget, - '--db', 'test', - '--collection', 'dest', - '--type=csv', - '--fields', 'a,b,c'] - .concat(commonToolArgs)); - assert.eq(0, ret); - - - // make sure only the specified fields were exported - assert.eq(3, destColl.count({a: 1})); - assert.eq(1, destColl.count({b: 1})); - assert.eq(1, destColl.count({b: 2})); - assert.eq(0, destColl.count({c: 3})); - - // success - toolTest.stop(); - -}());