I'm building a logging application that does the following:
gets JSON strings from many loggers continuously and saves them to a db
serves the collected data as a per logger bulk
my intention is to use a document based NoSQL storage to have the bulk structure right away. After some research I decided to go for MongoDB because of the following features:
- comprehensive functions to insert data into existing structures ($push, (capped) collection)
- automatic sharding with a key I choose (so I can shard on a per logger basis and therefore serve bulk data in no time - all data already being on the same db server)
The JSON I get from the loggers looks like this:
[
{"bdy":{
"cat":{"id":"36494h89h","toc":55,"boc":99},
"dataT":"2013-08-12T13:44:03Z","had":0,
"rng":23,"Iss":[{"id":10,"par":"dim, 10, dak"}]
},"hdr":{
"v":"0.2.7","N":2,"Id":"KBZD348940"}
}
]
The logger can send more than one element in the same array. I this example it is just one.
I started coding in Java with the mongo driver and the first problem I discovered was: I have to parse my with no doubt valid JSON to be able to save it in mongoDB. I learned that this is due to BSON being the native format of MongoDB. I would have liked to forward the JSON string to the db directly to save that extra execution time.
so what I do in a first Java test to save just this JSON string is:
String loggerMessage = "...the above JSON string...";
DBCollection coll = db.getCollection("logData");
DBObject message = (DBObject) JSON.parse(loggerMessage);
coll.insert(message);
the last line of this code causes the following exception:
Exception in thread "main" java.lang.IllegalArgumentException: BasicBSONList can only work with numeric keys, not: [_id]
at org.bson.types.BasicBSONList._getInt(BasicBSONList.java:161)
at org.bson.types.BasicBSONList._getInt(BasicBSONList.java:152)
at org.bson.types.BasicBSONList.get(BasicBSONList.java:104)
at com.mongodb.DBCollection.apply(DBCollection.java:767)
at com.mongodb.DBCollection.apply(DBCollection.java:756)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:220)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:204)
at com.mongodb.DBCollection.insert(DBCollection.java:76)
at com.mongodb.DBCollection.insert(DBCollection.java:60)
at com.mongodb.DBCollection.insert(DBCollection.java:105)
at mongomockup.MongoMockup.main(MongoMockup.java:65)
I tried to save this JSON via the mongo shell and it works perfectly.
How can I get this done in Java?
How could I maybe save the extra parsing?
What structure would you choose to save the data? Array of messages in the same document, collection of messages in single documents, ....
It didn't work because of the array. You need a BasicDBList to be able to save multiple messages. Here is my new solution that works perfectly:
BasicDBList data = (BasicDBList) JSON.parse(loggerMessage);
for(int i=0; i < data.size(); i++){
coll.insert((DBObject) data.get(i));
}
Related
i wanted to do a direct update to mongodb and setting someflag to either true or false for my use case. To be effecient i do not want to query all documents and set the someflag and save it back to db. i just want to directly update it on db just like when doing update on mongodb terminal.
Here is the sample document. NOTE: these documents can number from 1 ~ N so i need to handle efficiently big datas
{
_id: 60db378d0abb980372f06fc1
someid: 23cad24fc5d0290f7d5274f5
somedata: some data of mine
flag: false
}
Currently im doing an #Query method on my repository
#Query(value ="{someid: ?0}, {$set: {flag: false}}")
void updateFlag(String someid)
Using the above syntax, it doesnt work, i always get an exception message below;
Failed to instantiate void using constructor NO_CONSTRUCTOR with
arguments
How do i perform a direct update effeciently without querying all those document and updating it back to db?
Use the BulkOperations class (https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/BulkOperations.html)
Sample codes:
Spring Data Mongodb Bulk Operation Example
Scenario : I am trying to index json data into elastic . I am getting an error like
17:13:38.146 [main] ERROR
com.opnlabs.lighthouse.elastic.ElasticSearchIndexer -
{"root_cause":[{"type":"illegal_argument_exception","reason":"Can't
merge a non object mapping
[map.audits.map.font-size.map.details.map.items.myArrayList.map.selector]
with an object mapping
[map.audits.map.font-size.map.details.map.items.myArrayList.map.selector]"}],"type":"illegal_argument_exception","reason":"Can't
merge a non object mapping
[map.audits.map.font-size.map.details.map.items.myArrayList.map.selector]
with an object mapping
[map.audits.map.font-size.map.details.map.items.myArrayList.map.selector]"}
What is causing the issue ? Please help
Code
JSONObject newJsonObject = new JSONObject();
JSONObject log = jsonObject.getJSONObject("audits");
JSONObject log1 = jsonObject.getJSONObject("categories");
newJsonObject.put("audits", log);
newJsonObject.put("categories", log1);
newJsonObject.put("timeStamp", time);
Index index = new Index.Builder(newJsonObject).index(mongoIndexName+"1").type("data").build();
DocumentResult a = client.execute(index);
Basically i m trying to add 3 json values into elastic index. Please help me with what i m doing wrong.
The error message means that you are trying to change an existing mapping. However, that is not possible in Elasticsearch. Once a mapping has been created, it cannot be changed.
As explained by Shay Banon himself:
You can't change existing mapping type, you need to create a new index
with the correct mapping and index the data again.
So you must create a new index to create this mapping. Depending on the situation, you either
create an additional index, or
delete the current index and re-create it from scratch.
Of course in the latter case you will lose all data in the index, so prepare accordingly.
Taken from here : Can’t merge a non object mapping with an object mapping error in machine learning(beta) module
I am novice User to Couchbase, I am trying to insert the documents into the default bucket like below.
I found the following 2 ways to insert the json documents in the bucket:
1) Inserting by preparing JsonDocument and upsert into the bucket
StringBuilder strBuilder = new StringBuilder();
strBuilder.append("{'phone':{'y':{'phonePropertyList':{'dskFlag':'false','serialId':1000,'inputTray':{'LIST': {'e':[{'inTray':{'id':'1','name':'BypassTray','amount': {'unit':'sheets','state':'empty','typical':'0','capacity':'100'}");
String LDATA = strBuilder.toString();
Cluster cluster = CouchbaseCluster.create("localhost");
Bucket bucket = cluster.openBucket("default");
JsonObject deviceinfoObj = JsonObject.create().put("phoneinfo", LDATA);
bucket.upsert(JsonDocument.create("phone", deviceinfoObj));
2) Or by using like direct query like SQL
String query = "upsert into default(KEY, VALUE) values(LDATA)"
I am not able to find how to execute the above query like noram sql statement
Example:
Statement st = connection.createStatement();
ResultSet rs = st.executeQuery(query);
How to use N1QLQuery to insert the json document in the Couchbase Bucket.
I found the two ways to fetching the document.
i) Getting the document directly by using document Id
bucket.get("phone").content().get("phoneinfo")
ii) Getting the documents by using N!QueryResultSet
N1qlQueryResult result = bucket.query(N1qlQuery.simple("select * from default;"));
for (N1qlQueryRow row : result) {
System.out.println(row);
}
I got confused with the different approaches for inserting and fetching the documents from/to bucket in the Couchbase.
If I insert the documents by using 1st approach I need to prepare JsonObject with some key and value as a entire jsondocument.
So I think I better to insert the document using the second approach, So I will be able to fetch the documents using N1QLResultSet(2nd approach). but by using first approach I need to get the number of documents in the bucket and and then only I can loop through all the documents
Queries:
1) How to get the selective nested nodes from the document
2) In json document, Should I need to split key-value for each node ant then put in the JSONObject to prepare JSONDocument?
3) How to create a view for the bucket to do fast retrieval?
Why dont you create a simple java pojo and define it as a #Document. Then use CrudRepo to save and retrieve documents from couchbase.
this sample might help you:
https://github.com/maverickmicky/spring-couchbase-cache
I'm having a problem with MongoDB using Java when I try adding documents with customized _id field. And when I insert new document to that collection, I want to ignore the document if it's _id has already existed.
In Mongo shell, collection.save() can be used in this case but I cannot find the equivalent method to work with MongoDB java driver.
Just to add an example:
I have a collection of documents containing websites' information
with the URLs as _id field (which is unique)
I want to add some more documents. In those new documents, some might be existing in the current collection. So I want to keep adding all the new documents except for the duplicate ones.
This can be achieve by collection.save() in Mongo Shell but using MongoDB Java Driver, I can't find the equivalent method.
Hopefully someone can share the solution. Thanks in advance!
In the MongoDB Java driver, you could try using the BulkWriteOperation object with the initializeOrderedBulkOperation() method of the DBCollection object (the one that contains your collection). This is used as follows:
MongoClient mongo = new MongoClient("localhost", port_number);
DB db = mongo.getDB("db_name");
ArrayList<DBObject> objectList; // Fill this list with your objects to insert
BulkWriteOperation operation = col.initializeOrderedBulkOperation();
for (int i = 0; i < objectList.size(); i++) {
operation.insert(objectList.get(i));
}
BulkWriteResult result = operation.execute();
With this method, your documents will be inserted one at a time with error handling on each insert, so documents that have a duplicated id will throw an error as usual, but the operation will still continue with the rest of the documents. In the end, you can use the getInsertedCount() method of the BulkWriteResult object to know how many documents were really inserted.
This can prove to be a bit ineffective if lots of data is inserted this way, though. This is just sample code (that was found on journaldev.com and edited to fit your situation.). You may need to edit it so it fits your current configuration. It is also untested.
I guess save is doing something like this.
fun save(doc: Document, col: MongoCollection<Document>) {
if (doc.getObjectId("_id") != null) {
doc.put("_id", ObjectId()) // generate a new id
}
col.replaceOne(Document("_id", doc.getObjectId("_id")), doc)
}
Maybe they removed save so you decide how to generate the new id.
I'm trying to crawl the web and store HTML data on MongoDB using Java. Unfortunetely while storing data, MongoDB drivers nulling the data and stores empty field for HTML data.
When I get the first 500 chars of HTML data, I can store/upsert it without a problem so I think something in HTML (or Javascript in it) corrupts the command sent to MongoDB and MongoDB stores empty data instead of HTML. (EDIT: Also I've tried with 40.000 and 50.000 chars and 40.000 was OK but 50.000 char data didn't show up on MongoDB) Should I use something else for storing HTML/JavaScript data?
Here is my code snippet
BasicDBObject savedDoc = new BasicDBObject();
savedDoc.put("url_ID", objURL.get("_id"));
savedDoc.put("cnt", content); //Content field
savedDoc.put("st", 0);
collection.update(new BasicDBObject().append("url_ID", objURL.get("_id")), savedDoc, true, false);