So, I read my MongoDB this way:
mongo = new MongoClient("localhost", 27017);
// Accessing the database
MongoDatabase database = mongo.getDatabase("myDb");
MongoCollection<Document> collection = database.getCollection("searchresults");
// Getting the iterable object
FindIterable<Document> iterDoc = collection.find();
int i = 1;
// Getting the iterator
Iterator it = iterDoc.iterator();
while (it.hasNext()) {
System.out.println(it.next());
i++;
}
}
As you can see, each line has several columns: Title, etc. So, when I iterate over myDB, i want to parse each line by its value instead of get all in one line.
Any suggestions?
You can try reading into a Document structure, then run another loop across each of the entries. This will give each value on its own line.
FindIterable<Document> iterDoc = database.getCollection("").find();
for(Document doc : iterDoc) {
for(Map.Entry<String, Object> entry : doc.entrySet()) {
System.out.println("Key: " + entry.getKey() + " Value: " + entry.getValue());
}
}
If you only want certain keys, use a projection in your find query
This is not a fitting answer to your question, but i would look in to a concept thats called Object-Document-Mapping (ODM). It simplifies some boilerplate code that you have to care about. A common library for MongoDB-ODM is called Morphia :)
Related
I am new to MongoDB and trying to get a collection's result into java class object. While collection.find() returns a cursor to Document class and most of the operations are done on this class only, I tried putting a codecRegistry to my POJO. I can get some functions working but I dont have the flexibility as most of the methods work on Document class and I am unable to cast to my class.
FindIterable<Document> iterable = database.getCollection("bookingTest").find()
.sort(Sorts.ascending("bookingId"));
MongoCursor<Document> cursor1 = iterable.iterator();
List<Document> list1 = new ArrayList<Document>();
try {
while (cursor1.hasNext()) {
list1.add(cursor1.next());
}
}
finally {
cursor1.close();
}
for (Document document : list1) {
bookingMaster bm = new bookingMaster();
System.out.println("id is " + document.toJson().toString());
}
In this code, I am able to iterate over the cursor and I am getting the output as
id is {"_id": {"$oid": "5e93034001c18267dde36f5c"}, "bookingDay": "Tuesday", "bookingEndTime": "12:00", "bookingId": 1, "bookingPerson": "piyush.411031#gmail.com", "bookingStartTime": "10:00", "bookingTeam": "ADM"}
What I want to achieve is getting these output in an object of the class bookingMaster and use it the way I want.
Is there a way to do that??
With the driver Java Mongodb, I am looking for a way to return all fields of one collection.For example, I have a collection "people", how can I get all fields, I want output: 'id','name','city'...
Thanks a lot, I have finally got the answer.
DBCursor cur = db.getCollection("people").find();
DBObject dbo = cur.next();
Set<String> s = dbo.keySet();
From manual:
To return all documents in a collection, call the find method without a criteria document. For example, the following operation queries for all documents in the restaurants collection.
FindIterable<Document> iterable = db.getCollection("restaurants").find();
Iterate the results and apply a block to each resulting document.
iterable.forEach(new Block<Document>() {
#Override
public void apply(final Document document) {
System.out.println(document);
}
});
You'd need to decide on the number of samples that would make sense to you but this would pull the last 10 submissions.
Document nat = new Document().append("$natural",-1);
FindIterable<Document> theLastDocumentSubmitted = collection.find().limit(10).sort(nat);
ArrayList<String>fieldkeys = new ArrayList<String>();
for (Document doc : theLastDocumentSubmitted) {
Set<String> keys = doc.keySet();
Iterator iterator = keys.iterator();
while(iterator.hasNext()){
String key = (String) iterator.next();
String value = (String) doc.get(key).toString();
if(!fieldkeys.contains(key)) {
fieldkeys.add(key);
}
}
}
System.out.println("fieldkeys" + fieldkeys.toString());
Below code will return all fields from given collection.
MongoCollection<Document> mongoCollection = mongoDatabase.getCollection("collection_name");
AggregateIterable<Document> output = mongoCollection.aggregate(Arrays.asList(
new Document("$project", Document("arrayofkeyvalue", new Document("$objectToArray", "$$ROOT"))),
new Document("$unwind", "$arrayofkeyvalue"),
new Document("$group", new Document("_id", null).append("allkeys", new Document("$addToSet", "$arrayofkeyvalue.k")))
));
Below code will return all fields of people collection :
db.people.find()
The new AWS DynamoDB document API allows 2 new data types that correspond directly to the underlying JSON representation: Map (aka JSON object) and List (aka JSON array).
However, I can't find a way to update attributes of these data types without completely overwriting them. In contrast, a Number attribute can be updated by ADDing another number, so in Java you can do something like:
new AttributeUpdate("Some numeric attribute").addNumeric(17);
Similarly you can addElements to an attribute of a Set data type. (In the old API you would use AttributeAction.ADD for both purposes.)
But for a Map or a List, it seems you must update the previous value locally, then PUT it instead of that value, for example in Java:
List<String> list = item.getList("Some list attribute");
list.add("new element");
new AttributeUpdate("Some list attribute").put(list);
This is much less readable, and under some circumstances much less efficient.
So my questions are:
Is there a way to update an attribute of a Map or a List data type without overwriting the previous value? For example, to add an element to a List, or to put an element in a Map?
How would you implement it using the Java API?
Do you know of plans to support this in the future?
Please take a look at UpdateExpression in the UpdateItem API
For example given an item with a list:
{
"hashkey": {"S" : "my_key"},
"my_list" : {"L":
[{"N":"3"},{"N":"7"} ]
}
You can update the list with code like the following:
UpdateItemRequest request = new UpdateItemRequest();
request.setTableName("myTableName");
request.setKey(Collections.singletonMap("hashkey",
new AttributeValue().withS("my_key")));
request.setUpdateExpression("list_append(:prepend_value, my_list)");
request.setExpressionAttributeValues(
Collections.singletonMap(":prepend_value",
new AttributeValue().withN("1"))
);
dynamodb.updateItem(request);`
You can also append to the list by reversing the order of the arguments in the list_append expression.
An expression like: SET user.address.zipcode = :zip would address a JSON map element combined with expression attribute values {":zip" : {"N":"12345"}}
Base on DynamoDB examples, this also work (scala)
val updateItemSpec:UpdateItemSpec = new UpdateItemSpec()
.withPrimaryKey("hashkey", my_key)
.withUpdateExpression("set my_list = list_append(:prepend_value, my_list)")
.withValueMap(new ValueMap()
.withList(":prepend_value", "1"))
.withReturnValues(ReturnValue.UPDATED_NEW)
println("Updating the item...")
val outcome: UpdateItemOutcome = table.updateItem(updateItemSpec)
println("UpdateItem succeeded:\n" + outcome.getItem.toJSONPretty)
A generic function to add or update a key/value pairs. attribute updateColumn should be of type map.
Update tableName attribute name should be passed as attributeName under key:value pairs where primaryKey = primaryKeyValue
public boolean insertKeyValue(String tableName, String primaryKey, String
primaryKeyValue, String attributeName, String newKey, String newValue) {
//Configuration to connect to DynamoDB
Table table = dynamoDB.getTable(tableName);
boolean insertAppendStatus = false;
try {
//Updates when map is already exist in the table
UpdateItemSpec updateItemSpec = new UpdateItemSpec()
.withPrimaryKey(primaryKey, primaryKeyValue)
.withReturnValues(ReturnValue.ALL_NEW)
.withUpdateExpression("set #columnName." + newKey + " = :columnValue")
.withNameMap(new NameMap().with("#columnName", attributeName))
.withValueMap(new ValueMap().with(":columnValue", newValue))
.withConditionExpression("attribute_exists("+ attributeName +")");
table.updateItem(updateItemSpec);
insertAppendStatus = true;
//Add map column when it's not exist in the table
} catch (ConditionalCheckFailedException e) {
HashMap<String, String> map = new HashMap<>();
map.put(newKey, newValue);
UpdateItemSpec updateItemSpec = new UpdateItemSpec()
.withPrimaryKey(primaryKey,primaryKeyValue)
.withReturnValues(ReturnValue.ALL_NEW)
.withUpdateExpression("set #columnName = :m")
.withNameMap(new NameMap().with("#columnName", attributeName))
.withValueMap(new ValueMap().withMap(":m", map));
table.updateItem(updateItemSpec);
insertAppendStatus = true;
} catch(Exception e) {
e.printStackTrace();
}
return insertAppendStatus;
}
I am trying to do fetch the data from database using ScrollableResults. Part of my code is below :
List list = null;
ScrollableResults items = null;
String sql = " from " + topBO.getClass().getName(); // topBO is my parent class so i pass the any of my child class name .
StringBuffer sqlQuery = new StringBuffer(sql);
Query query = sessionFactory.getCurrentSession().createQuery(sqlQuery.toString());
items = query.scroll();
int i = 0;
TopBO topBO;
while(items.next())
{
topBO= (TopBO) items.get()[i];
list.add(TopBO2); // got the exception at this line.
i++;
topBO= null;
}
items.close();
If i run the above code i am getting runtime error like java.lang.NullPointerException
You are trying to add the value in list which is not initialize.
It may helps you :
List list = new ArrayList();
replace with
List list = null;
I think topBO= (TopBO) items.get()[i]; is causing the problem.
I would suggest that you use result set transformer of query something like this
Query query = sessionFactory.getCurrentSession().createQuery(sqlQuery.toString());
list=query.setResultTransformer(Transformers.aliasToBean(YourClassName.class)).list();
currently have a cypher query method
public static void RunQuery(String _query)
{
Properties prop = new Properties();
final String DB_PATH = "path/to/db"
GraphDatabaseService graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);
ExecutionEngine engine = new ExecutionEngine(graphDb);
ExecutionResult result = engine.execute(_query);
for(Map<String,Object> map : result)
{
System.out.println(map.toString());
}
graphDb.shutdown();
}
However this only allows me to get results like this:
{a=Node[11303]}
{a=Node[11341]}
{a=Node[11343]}
{a=Node[11347]}
{a=Node[11349]}
{a=Node[11378]}
How can I augment it to spit out the entire query results like the cypher shell does?
What does your query look like. The Map<String, Object> that is returned will have a key of the variable you return. The Object can be a Path, Node, or Relationship, and this will just call the native toString() on them, which in Java code just returns the Node ID. You have to build your own printer, something that will get the property keys and iterate through each of them.
for (String key : node.getPropertyKeys()) {
System.out.println("Key: " + key + ", Value: " + node.getProperty(key));
}
It depends on the RETURN of your query..
For example, if you have a query like this:
_query="Start x= node(someIndex) Match x-[rel:SOMETHING]-n Return n";
So, your code can be
ExecutionResult result = engine.execute(_query);
Iterator<Node> n_column = result.columnAs("n");
for (Node outputNode: IteratorUtil.asIterable(n_column)) {
System.out.println(outputNode.getProperty("yourKey","defaultValueIfNull"));
}