1

I am working on inserting a CSV file into MongoDB. First I am converting my CSV into Json formatted array (Reference: https://dzone.com/articles/how-to-convert-csv-to-json-in-java) and then trying to upload it into MongoDB, but facing the below error(readStartDocument can only be called when CurrentBSONType is DOCUMENT, not when CurrentBSONType is ARRAY.):

Exception in thread "main" org.bson.BsonInvalidOperationException: readStartDocument can only be called when CurrentBSONType is DOCUMENT, not when CurrentBSONType is ARRAY.
    at org.bson.AbstractBsonReader.verifyBSONType(AbstractBsonReader.java:692)
    at org.bson.AbstractBsonReader.checkPreconditions(AbstractBsonReader.java:724)
    at org.bson.AbstractBsonReader.readStartDocument(AbstractBsonReader.java:452)
    at org.bson.codecs.DocumentCodec.decode(DocumentCodec.java:148)
    at org.bson.codecs.DocumentCodec.decode(DocumentCodec.java:45)
    at org.bson.Document.parse(Document.java:105)
    at org.bson.Document.parse(Document.java:90)
    at com.ucm.json.ConnectMongoDB.connectToMongoDB(ConnectMongoDB.java:52)
    at com.ucm.json.Main.main(Main.java:15)

My JSON string(result) looks like below:

[ {
  "query" : "ecn",
  "type" : "KeywordMatch",
  "url" : "http://insidedell.com/ecn",
  "description" : "ECN"
}, {
  "query" : "product marketing",
  "type" : "PhraseMatch",
  "url" : "http://dellemc.com/product",
  "description" : "Products"
}, {
  "query" : "jive",
  "type" : "ExactMatch",
  "url" : "http://test.com/jive",
  "description" : "Jive test"
} ]

Below is my code: Step 1: Convert CSV into JSON format string array

public class CreateJSON {

    public String query;
    public String type;
    public String url;
    public String description; 
    String result ;
    public CreateJSON() {

    }
    public CreateJSON(String query,String type,String url,String description) {
        this.query = query;
        this.type = type;
        this.url = url;
        this.description = description;

    }

    public String createJsonFromCSV() throws IOException{
        String csvFile = "C:\\Projects\\frontKeymatch_default_frontend.csv";

        List<CreateJSON> createObjects = null;
        Pattern pattern = Pattern.compile(",");
        try (BufferedReader in = new BufferedReader(new FileReader(csvFile));){

            createObjects = in.lines().map(line ->{
                String[] x = pattern.split(line);
                return new CreateJSON(x[0],x[1],x[2],x[3]);

            }).collect(Collectors.toList());


             ObjectMapper mapper = new ObjectMapper();
             mapper.enable(SerializationFeature.INDENT_OUTPUT);
             result =  mapper.writeValueAsString(createObjects);

        } 
         return result;

    }
}

Step 2) Connect to MongoDB and insert the data

public class ConnectMongoDB{
    public void connectToMongoDB(String resultFromCSV) throws JsonGenerationException, JsonMappingException, IOException {

    MongoClient mongo = new MongoClient( "localhost" ,27017);
    Document doc = Document.parse(resultFromCSV);

            mongo.getDatabase("db").getCollection("collection").insertOne(doc);

            System.out.println("success");

        }
   }    

Step 3: My main method:

public class Main {

    public static void main(String[] args) throws FileNotFoundException, IOException {

        CreateJSON upload = new CreateJSON();
        ConnectMongoDB mongo = new ConnectMongoDB();
        mongo.connectToMongoDB(upload.createJsonFromCSV());
    }

}

Any help is appreciated. Thanks

6
  • Are you trying to insert the entire csv file as a single array document in mongodb ? Document.parse is designed to work with single document not arrays. Commented Mar 2, 2018 at 0:16
  • @Veeram Yes. Is that not a right way to do? Commented Mar 2, 2018 at 0:17
  • It depends what you wanting to do with it. Take a look at this answer. It may help you. Commented Mar 2, 2018 at 0:17
  • @Veeram Basically, I want to store it in MongoDB collection and then later access the collection from another java application and get values like for a particular query, get its type,url and description. Commented Mar 2, 2018 at 0:22
  • Okay then you should save them as separate documents. Commented Mar 2, 2018 at 0:23

2 Answers 2

2

There is no direct conversion from json array to Document. Document.parse works with single document and is the reason for error.

You can update your method to remove the intermediate CreateJSON object and ObjectMapper and directly map the csv line to Document and collect them as List.

Move the below method to main class as static method and use InsertMany to insert all document.

Main method.

public class Main {

public static void main(String[] args) throws FileNotFoundException, IOException {
    ConnectMongoDB mongo = new ConnectMongoDB();
    mongo.connectToMongoDB(createJsonFromCSV());
}

public static List<Document> createJsonFromCSV() throws IOException {
    String csvFile = "C:\\Projects\\frontKeymatch_default_frontend.csv";
    List<Document> createObjects = null;
    Pattern pattern = Pattern.compile(",");
    try (BufferedReader in = new BufferedReader(new FileReader(csvFile));){
          createObjects = in.lines().map(line ->{
             String[] x = pattern.split(line);
             return new Document("query",x[0]).append("type", x[1]) //append other fields
          }).collect(Collectors.toList());
       }
     return createObjects;
    }
}

public class ConnectMongoDB{
    public void connectToMongoDB(List<Document> docs) throws IOException {
    MongoClient mongo = new MongoClient( "localhost" ,27017);
    mongo.getDatabase("db").getCollection("collection").insertMany(docs);
    System.out.println("success");
   }
}   
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. I wil try this and let you know
It worked. Minor typo error in your code. It should be insertMany instead of insertAll. Thanks a lot!!
0

In my case, I missed the curly brackets around group pipline in my MongoRepository i.e. I wrote

@Aggregation(pipeline = {
        "$group: { _id: { $dateToString: { date: '$createdDate', format: '%Y-%m' } }, count: { $sum: 1 } }"
})
AggregationResults<SubmissionCount> getSubmissionsCountPerMonth();

instead of

@Aggregation(pipeline = {
        "{ $group: { _id: { $dateToString: { date: '$createdDate', format: '%Y-%m' } }, count: { $sum: 1 } } }"
})
AggregationResults<SubmissionCount> getSubmissionsCountPerMonth();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.