MongoDB Reading from Nested Documents - java

I have a document with nested documents within, I thought as per a filter I would be able to specify something like data.sms.mobileNumber. However that doesn't work.
How would I read the data in the data.sms.mobileNumber field, using the the standard Document getString request?
Example Document:
{ "_id" : ObjectId("59b850bd81bacd0013d15085"), "data" : { "sms" : { "message" : "Your SMS Code is ABCDEFG", "mobileNumber" : "+447833477560" } }, "id" : "b0a3886d69fc7319dbb4f4cc21a6039b422810cd875956bfd681095aa65f6245" }
Example Field get String request:
document.getString("data.sms.message")

The 'path' data.sms.message refers to a structure like this:
+- data
|
+- sms
|
+- message
To read this using the Java driver you have to read the data document, then the sms sub document then the message attribute of that sub document.
For example:
Document data = collection.find(filter).first();
Document sms = (Document) data.get("sms");
String message = sms.getString("message");
Or, the same thing with shortcuts:
String message = collection.find(filter).first()
.get("sms", Document.class)
.getString("message");
Update 1 in answer to this question: "I have a case where I have an array of documents in a document, how would I go about getting a field from a document in the array?" Let's assume you have a document with an array field named details and each detail has name and age. Something like this:
{"employee_id": "1", "details": [{"name":"A","age":"18"}]}
{"employee_id": "2", "details": [{"name":"B","age":"21"}]}
You could read the array element like so:
Document firstElementInArray = collection.find(filter).first()
// read the details as an Array
.get("details", ArrayList.class)
// focus on the first element in the details array
.get(0);
String name = firstElementInArray.getString("name");

Related

Jackson objectMapper gives different object for same json

I'm passing a json to objectmapper. The JSON string looks like this:
{
"id": "ID1",
"identifier" : "XYZ",
"data": [
{
"id": "sampleParentID",
"childrenElements": [
{
"id" : "sampleChildID",
"content" : "sample child content",
}
]
}
]
}
val objectMapper = ObjectMapper().registerModule(KotlinModule())
val obj: Object1 = objectMapper.readValue(jsonString)
My class looks something like this :
data class Object 1 (
var id : String? = null,
var identifier : String? = null,
var data: MutableList<Element>? = null,
){
// some functions
}
class Element (
var id : String?= null
var content : String? = null
var children: List<Element>? = listOf(),
) {
// som functions
}
From obj, data field is nested which is an object itself.
I want to get hashCode of data so I do obj.data.hashCode(). Let's say 12345 gets generated.
I store this in the database. Now, let's say the user sends another request with exactly the same JSON, again the JSON gets converted into an object from which I extract the data field and now when I do obj.data.hashCode(), 12345 is not generated, rather some other number gets generated.
Is this behavior expected? If yes, what is the workaround?
Update : Added classes description.
Given that your Element class is not a data class (in this case you would get a hashCode() method implementation based on all class properties) you will need to write the hashCode() method yourself so that the default one (based on object memory reference) is not used and you get rid of the behaviour you are currently facing.

MongoDB nested query returning null with Java driver

I'm attempting to get the 'code' from the 'DEBIT' field from a mongodb collection formatted as follows:
"_id" : ObjectId("1"),
{...}
"bookEntryActions" : {
"CREATE" : [
{
"nature" : "DEBIT",
"code" : "123"
},
{
"nature" : "CREDIT",
"code" : "456"
}
],
"DELETE" : [
{
"nature" : "DEBIT",
"code" : "123"
},
{
"nature" : "CREDIT",
"code" : "789"
}
]
{...}
}
I've tried the following methods:
Method #1:
Document debitGlAccountCode = (Document)landlord.get("bookEntryActions.CREATE.1");
Method #2:
Document bookEntryActions = (Document) landlord.get("bookEntryActions");
Document creationRentCodes = (Document) bookEntryActions.get("CREATE");
ObjectId debitGlAccountCode = (ObjectId) creationRentCodes.get(Filters.eq("nature", "DEBIT"));
Method #3:
ObjectId debitGlAccountCode = (ObjectId) landlord.get(Filters.eq("bookEntryActions.CREATE.nature", "DEBIT"));
My issue is that of all the methods I've tried, the return for the .get("CREATE") is null. Does anyone have any idea what the issue could be? I've verified that the CREATE field exists for all of the landlords using Robo3T.
Edit: each variable has gotten the data as follows
final MongoCollection<Document> landlordCollection = db.getCollection("landlord");
final FindIterable<Document> landlordDocs = landlordCollection.find();
MongoCursor<Document> llDocIter = landlordDocs.iterator();
while(llDocIter.hasNext()){
Document landlord = llDocIter.next();
LOGGER.info("landlord bookEntryActions: " + landlord.get("bookEntryActions"));
LOGGER.info("landlord create: " + landlord.get("bookEntryActions.CREATE"));
landlordArrayList.add(landlord);
}
From there I have a foreach loop which goes through all the landlords in the arrayList and is where the previously attempted methods above are used. (Note: I'm using the array list for now as it's a little easier to work with while debugging. Eventually I will do everything in the while loop).
It turns out that the way the database was set up "CREATE" is an array list of documents and thus I had just been working with the wrong data types. Upon adapting the code to work with the arraylist and not a Document its working.

Cassandra Saving JSON data in Text Column

In Cassandra DB I have column name as custom_extensions which can contain List<AppEncoded> where AppEncoded is an UDT. The UDT has following fields
type -> TEXT
code -> TEXT
value - TEXT
While saving data to DB the value field can expect input as object.
CurrencyTO:
field -> amount
field -> Symbol
field -> formattedAmount
The implementation to save the column value in DB is as follows:
JacksonJsonCodec<CurrencyTO> jacksonJsonCodec = new JacksonJsonCodec<>(CurrencyTO.class);
appEncodedValue.setValue(jacksonJsonCodec.format(CurrencyTO.getValue()));
CurrencyTo is extending TranserObject which has following attributes as well.
If I see in DB I am seeing the following results:
"value": "'{\"serviceResult\":{\"messagesResult\":[]},\"attributeNames\":[\"amount\",\"isoCode\",\"symbol\",\"decimalValue\",\"formattedAmount\"],\"metadata\":null,\"this\":null,\"amount\":\"45\",\"isoCode\":\"USD\",\"symbol\":\"$\",\"decimalValue\":2.0,\"formattedAmount\":null}'"
The result added the serviceResult, messageResult, metadata and some \ characters as well.
The Expected Result Should be similar as following in DB
"value": {
"amount": 90,
"Symbol": "$",
"formattedAmount" : "90.00"
}
The Reference I followed for implementation is:
custom_codecs

MongoDB query in nested key value and compare inside value list

My database looks like
{
"_id" : ObjectId("5a8351093cf24e144d8fef24"),
"__type" : "TrafficIncident:http://schemas.microsoft.com/search/local/ws/rest/v1",
"point" : {
"type" : "Point",
"coordinates" : [
37.410883,
-95.71027
]
},
...
}
{
"_id" : ObjectId("5a8351093cf24e144d8fef25"),
"__type" : "TrafficIncident:http://schemas.microsoft.com/search/local/ws/rest/v2",
"point" : {
"type" : "Point",
"coordinates" : [
40.2346,
-100.826167
]
},
...
}
If I have a coordinates pair as center location, say [38, -98], and I want to retrieve all records with in coordinate range [38 +- 2, -98 +- 2], how to write java code for the Document Filter?
So far what I have done is retrieving a specific location instead of inside a range.
Document query = new Document("point.coordinates", Arrays.asList(40.2346, -100.826167));
javamongo.collection.find(query).limit(javamongo.numLimit).forEach(printBlock);
You'll want to use MongoDB's Geospatial Query system for this.
I'm assuming you're using Mongo's official Java Driver. First you'll want to create a 2dsphere index on the point.coordinates field. You can do this in Java with:
collection.createIndex(Indexes.geo2dsphere("point.coordinates"));
Then you can query for all documents within your location range with:
Point refPoint = new Point(new Position(38, -98));
collection.find(Filters.near("point.coordinates", refPoint, 2, 2)).forEach(printBlock);
MongoDB's tutorial on geospatial search with their Java driver is pretty good.

Cloudera Navigator API fail to fetch nested data

I am working in Cloudera Manager Navigator REST API where extracting result is working fine, but unable to get any nested value.
The type of data is extracting as below.
{
"parentPath": "String",
"customProperties": "Map[string,string]",
"sourceType": "String",
"entityType": "String"
}
And data should be like
{
"parentPath": "abcd",
"customProperties": {
"nameservice" : "xyz"
},
"sourceType": "rcs",
"entityType": "ufo"
}
But I am getting key-value result as follows.
parentPath :abcd
customProperties : null
sourceType : rcs
entityType : ufo
In above response data, "customProperties" is coming with a null value where it should return a map object contains ["nameservice" : "xyz"]. This is the problem with following code snippet.
MetadataResultSet metadataResultSet = extractor.extractMetadata(null, null,"sourceType:HDFS", "identity:*");
Iterator<Map<String, Object>> entitiesIt = metadataResultSet.getEntities().iterator();
while(entitiesIt.hasNext()){
Map<String, Object> result = entitiesIt.next();
for(String data : result.keySet()){
System.out.println(" key:"+data+" value:"+result.get(data));
}
}
Can you suggest me how to get the nested value where datatype is complex.
have u checked how the data looks on navigator ui? You can first verify that once, and also try cloudera /entities/entity-id rest API in browser to check how json response is coming

Categories