I want to convert a CSV line into a GeoJSON object. I am using CSVReader. Hence, nextLine[] has all the separated tokens.
I want to create BasicDBObject which has various attributes stored. I am doing it following way.
new BasicDBObject("attribute1",nextLine[0]).append("attribute2",nextLine[1])
What I want to achieve is having a document like this in MongoDB
{
attribute1: name
attribute2: address
location:{ type : "Point" ,
coordinates : [lat, long]
}
attrribute3: phonenumber
}
How do I do this using BasicDBObject?enter code here
The easiest way to do that is using the BasicDBObjectBuilder, an utility class to build DBObjects. You can do something like that:
BasicDBObject toInsert = BasicDBObjectBuilder.start()
.add("attribute1",nextLine[0])
.add("attribute2",nextLine[1])
.add(" attrribute3",nextLine[2])
.push("location")
.add("type", "Point")
.add("coordinates", new double[] { nextLine[3], nextLine[4] })
.pop()
.get()
I did it the other way
double latLong[] = new double[]{10.0, 30.0};
BasicDBObject doc = new BasicDBObject("attr1",nextLine[0])
.append("attr2", nextLine[1]
.append("location",new BasicDBObject("type","Point")
.append("coordinates",latLong))
.append("attr3", nextLine[3])
This also works as desired
Related
I'm not sure what format this object is in but can I parse the following invalid JSON object to Java class Pojo? I tried doing it using Jackson but since it's invalid, I was wondering if pojo class would work?
{
name: (sindey, crosby)
game: "Hockey"
type: athlete
}
The file would have multiple objects of this format
Geesh, don't recognise this format! If you want to use Jackson you could pre-process you data to wrap the values... perhaps a regex to catpure the groups and wrap the values in quotes something like (name|type):\s(.+) => $1: "$2"
I was wondering if pojo class would work?
Sure, you could make that work with a simple parser; plenty of room for improvement, but something like this would do it:
Record record = null;
var records = new LinkedList<>();
// I'm using a reader as example, but just provide lines any way you like
while ((line = reader.readLine()) != null) {
line = line.trim();
// may need to skip empty lines if you have them in your file...
if (line.equals("{")) {
record = new Record();
records.add(record);
} else {
// may need substrings if your data contains ":"
var tokens = line.split(":");
var field = tokens[0];
var value = tokens[1];
if (field.equals("name")) {
// perhaps shuffle the format to something nicer here..
record.setName(value);
}
/// same for game and type fields...
}
}
I got a JSON string that looks something like this:
String tmp = "[
{
"ID":"12",
"Date":"2018-02-02",
"ObjData":[
{
"Name":"AAA",
"Order":"12345",
"Extra1":{
"Temp":"3"
},
"Extra2":{
"Temp":"5"
}
},
{
"Name":"BBB",
"Order":"54321",
"Extra1":{
"Temp":"3"
},
"Extra2":{
"Temp":"5"
}
}
]
}
]"
I would like to remove for example the the document where ´Order´ equals "54321" from ´ObjData´. I got the following code:
Document doc = new Document();
doc = Document.parse(tmp);
Document fields = new Document("ID", "12")
.append("ObjData", Arrays.asList(new Document("Order", "54321")));
Document update = new Document("$pull", fields);
coll.updateOne(doc, update);
I am trying to use the ´pull´ method to remove the entire document from the array where the ´Order´ equals 54321 but for some reason it's not working, I am probably doing something wrong. Could someone point out the issue please?
Also, what would be the best way to keep count of the documents within the array so that once all documents are pulled the entire document is deleted from the database? Would it be good to add some kind of ´size´ attribute and keep track of the size and decrease it after each pull?
To remove document with Order=54321 from internal array from any document (if you don't know ID) you can use empty filter like:
Document filter = new Document();
Document update = new Document("$pull", new Document("ObjData", new Document("Order", "54321")));
coll.updateOne(filter, update);
Updating records to remove values from ObjData array
The first parameter to the updateOne method is a query to find the document you want to update, not the full document.
So for your code, assuming ID is a unique value and that there's an item in your collection with an ID of "12":
// { ID: "12" }
Document query = new Document("ID", "12");
// { ObjData: { $pull: { Order: "54321" } } }
Document update = new Document("ObjData",
new Document("$pull",
new Document("Order", "54321")
)
);
coll.updateOne(query, update);
Alternatively, if you want to remove the order from all documents in the database, just replace query with an empty Document, i.e.:
// { <empty> }
Document query = new Document();
Deleting records with empty ObjData array
As for removing records when the size reaches zero, you can use a filter with $size:
db.myColl.deleteMany({ ObjData: { $size: 0 } })
This is also doable using the Java driver:
// { ObjData: { $size: 0 } }
Document query = new Document("ObjData",
new Document("$size", 0)
);
coll.deleteMany(query);
Note that for large collections (i.e. where myColl is large, not the ObjData array), this may not perform very well. If this is the case, then you may want to track the size separately (as you hinted at in your question) and index it to make it faster to search on since you can't create an index on array size in MongoDB.
References
updateOne documentation for updating documents using the Java driver
deleteOne documentation for deleting documents using the Java driver
$pull documentation for removing documents from an array
$size documentation for filtering documents based on the size of an array
I'm trying to insert a string that represents a JSON array into a mongodb collection with this,
String str = "[{\"id\":1,\"data\":\"data1\"},{\"id\":2,\"data\":\"data2\"},{\"id\":3,\"data\":\"data3\"}]";
DBObject dbObject = (DBObject) JSON.parse(str);
collection.insert(dbObject);
But I get the exception,
Exception in thread "main" java.lang.IllegalArgumentException: BasicBSONList can only work with numeric keys, not: [_id]
Can anyone show me the correct way to do this?
String json = "[{\"id\":1,\"data\":\"data1\"},{\"id\":2,\"data\":\"data2\"},{\"id\":3,\"data\":\"data3\"}]";
MongoCredential credential = MongoCredential.createCredential("root", "sample", "root".toCharArray());
MongoClient mongoClient = new MongoClient(new ServerAddress("localhost"), Arrays.asList(credential));
MongoDatabase db = mongoClient.getDatabase("sample");
MongoCollection<Document> collection = db.getCollection("loginTracking");
List<Document> jsonList = new ArrayList<Document>();
net.sf.json.JSONArray array = net.sf.json.JSONArray.fromObject(json);
for (Object object : array) {
net.sf.json.JSONObject jsonStr = (net.sf.json.JSONObject) JSONSerializer.toJSON(object);
Document jsnObject = Document.parse(jsonStr.toString());
jsonList.add(jsnObject);
}
collection.insertMany(jsonList);
mongoClient.close();
as per java doc the insert() can accept either single DBObject or an array or List of them.
So, in order to save, you need to convert your JSON array into an array/List of DBObjects, or save each array's item
I found a good way for achieve that:
(ArrayList<Document>) JSON.parse("[String json array]");
I had a problem with this, because i need append to this document a property that is a Json Array:
Document objAddendumVersion = new Document();
objAddendumVersion.append("_id", new ObjectId());
objAddendumVersion.append("Array", My Array here!);
But the problem is that Document.parse() doesn't work with Arrays, so i could solve it using the above line. So the final code is:
Document objAddendumVersion = new Document();
objAddendumVersion.append("_id", new ObjectId());
objAddendumVersion.append("Array", (ArrayList<Document>) JSON.parse("[String json array]"));
And it works perfect. Yes i know that exist more better ways for do that, but for the moment i'm using this.
I wait that be useful for someone with the same trouble.
I am trying to parse a csv string like this
COL1,COL2,COL3
1,2,3
2,4,5
and map columns to a java object-
Class Person{
COL1,
COL2,
COL3;
}
Most of the libraries I found on google are for csv files but I am working with google app engine so can't write or read files. currently I am using split method but problems with this approach is
column that I am getting in csv string could vary as
COL1,COL3,COL2
don't want to use boiler plate code of splitting and getting each column.so what I need is list of column header and read all columns in a collection using header mapper. While iterating, map column value to a java object.
There are several question based on similar type of requirement but none of them helped me.
If anyone has done this before please could you share the idea? Thanks!
After searching and trying several libraries, I am able to solve it. I am sharing the code if anyone needs it later-
public class CSVParsing {
public void parseCSV() throws IOException {
List<Person> list = Lists.newArrayList();
String str = "COL1,COL2,COL3\n" +
"A,B,23\n" +
"S,H,20\n";
CsvSchema schema = CsvSchema.emptySchema().withHeader();
ObjectReader mapper = new CsvMapper().reader(Person.class).with(schema);
MappingIterator<Person> it = mapper.readValues(str);
while (it.hasNext()) {
list.add(it.next());
}
System.out.println("stored list is:" + (list != null ? list.toString() : null));
}}
Most of the libraries I found on google are for csv files but I am
working with google app engine so can't write or read files
You can read file (in project file system).
You can read and write file in blobstore, google cloud storage
Use a Tokenizer to split the string into objects then set them to the object.
//Split the string into tokens using a comma as the token seperator
StringTokenizer st = new StringTokenizer(lineFromFile, ",");
while (st.hasMoreTokens())
{
//Collect each item
st.nextElement();
}
//Set to object
Person p = new Person(item1, item2, item3);
If the columns can be reversed, you parse the header line, save it's values and and use it to decide which column each token falls under using, say, a Map
String columns[] = new String[3]; //Fill these with column names
Map<String,String> map = new HashMap<>();
int i=0;
while (st.hasMoreTokens())
{
//Collect each item
map.put(columns[i++], st.nextElement());
}
Then just, create the Person
Person p = new Person(map.get("COL1"), map.get("COL2"), map.get("COL3"));
I have a JSON in MongoDB with the following structure:
{
id:"_234234",
"stationId":"ALM",
"storageData": {
}
}
To retrieve JSON with storageData equal to null, in MongoDB I query as:
db.collection.find({"storageData":{"$gt" : {}}})
It gives me list of JSON bodies with empty storageData. So how do I represent that in Java
BasicDBObject obj=new BasicDDBObject("storageData", new BasicDBObject("$gt",{}));
collection.find(obj);
I am getting an error near BasicDBObject("$gt",{}))...
How do I represent ("$gt",{}) in Java??
First understand that null is a valid value. This would be valid:
{
id:"_234234",
StationId:"ALM",
StorageData: null
}
and retrieving the document, asking for storagedata which is null would retrieve the doc with the id _234234.
If what you need is to check which documents DON'T have the key "storagedata" then use the $exist keyword or construct the query in this way:
db.yourcollection.find("this.storagedata == null")
I would do it via query, and not in Java because it would alleviate cpu time and memory.
All you want to to here is represent an empty object:
BasicDBObject query = new BasicDBObject(
"storageData", new BasicDBObject(
"$gt",new BasicDBObject()
)
);
Which of course produces the query:
{ "storageData" : { "$gt" : { } } }
So that's it, just call BasicDBObject without any arguments.