I just started using Java and MongoDB. I want to retrieve some data from my database and store it in a list. I want to get a list with only coordinates. (see sample JSON code).
I believe I currently have a list with all the objects in the collection. I only want the coordinates from the data, and store it into a list, I really don't know how to do it.
This is my java code(the connectToMongoCollection method makes (obviously) connection to my database:
DBCollection collection = DBCollections.connectToMongoCollection("collection");
BasicDBList basicDBList = new BasicDBList();
DBCursor cursor = collection.find(new BasicDBObject("type", "feature"));
try {
while(cursor.hasNext()) {
basicDBList.add(cursor.next());
}
} finally {
cursor.close();
}
for(Object object: basicDBList){
BasicDBObject basicDBObject = (BasicDBObject) object;
}
This is the format of a sample MongoDB document.
"features": [
{"type": "Feature",
"properties": { "OBJECTID": 1, "Join_Count": 1, "LABEL": 0 },
"geometry": { "type": "MultiPoint", "coordinates": [ [ 4.3434010517041, 51.891054440280314 ] ] } }
I hope someone can help me, Thanks in advance.
This code will give you coordinates from data stored in a BasicDBList.
public static void main(String[] args) {
try {
MongoClient mongoClient = new MongoClient("localhost", 27017);
DB db = mongoClient.getDB("StackOverflow");
DBCollection dbcol = db.getCollection("features");
DBCursor cursor = dbcol.find();
try {
while (cursor.hasNext()) {
DBObject Features = cursor.next();
BasicDBList features = (BasicDBList) Features.get("features");
BasicDBObject[] featuresArr = features.toArray(new BasicDBObject[0]);
for (BasicDBObject dbobj : featuresArr) {
BasicDBObject geometry = (BasicDBObject) dbobj.get("geometry");
BasicDBList coordinates = (BasicDBList) geometry.get("coordinates"); // BasicDBList contains coordinates
System.out.println(coordinates.get(0));
}
}
} finally {
cursor.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
This must be your sample mongodb document
{ "features": [
{
"type": "Feature",
"properties": {
"OBJECTID": 1,
"Join_Count": 1,
"LABEL": 0
},
"geometry": {
"type": "MultiPoint",
"coordinates": [
[
4.3434010517041,
51.891054440280314
]
]
}
}
]
}
and output is [ 4.3434010517041 , 51.891054440280314]
I inserted this document in database "StackOverflow" and collection name is "features"
Here's another way to do it. Not necessarily better, but perhaps easier on the person digesting the data.
I am assuming that each doc has a features field that is an array of things including coordinates which can be array of coordinates (not just one). Here are two such docs in collection foo (removed the other fields that aren't important):
db.foo.find().pretty();
{
"_id" : ObjectId("55735cccdbc638d309795958"),
"features" : [
{
"geometry" : {
"type" : "MultiPoint",
"coordinates" : [ [ 1.2, 3.4 ] ]
}
},
{
"geometry" : {
"type" : "MultiPoint",
"coordinates" : [ [ 5.6, 7.8 ] , [ 9.1, 11.12 ] ]
}
}
]
}
{
"_id" : ObjectId("55735cccdbc638d309795959"),
"features" : [
{
"geometry" : {
"type" : "MultiPoint",
"coordinates" : [ [ 83, 94 ] , [ 0.4, 0.5 ] ]
}
},
{
"geometry" : {
"type" : "MultiPoint",
"coordinates" : [ [ 8.3434010517041, 9.891054440280314 ] ]
}
}
]
}
Here's a nice way to use the aggregation framework to unwind all those "arrays within arrays" to give you the 6 coordinate pairs you seek.
db.foo.aggregate([
... {$unwind: "$features"}
... , {$project: { coord: "$features.geometry.coordinates", "_id":0} }
... , {$unwind: "$coord"}
... ]);
{ "coord" : [ 1.2, 3.4 ] }
{ "coord" : [ 5.6, 7.8 ] }
{ "coord" : [ 9.1, 11.12 ] }
{ "coord" : [ 83, 54 ] }
{ "coord" : [ 0.4, 0.5 ] }
{ "coord" : [ 8.3434010517041, 9.891054440280314 ] }
Related
How can I find the number of duplicates in each document in Java-MongoDB
I have collection like this.
Collection example:
{
"_id": {
"$oid": "5fc8eb07d473e148192fbecd"
},
"ip_address": "192.168.0.1",
"mac_address": "00:A0:C9:14:C8:29",
"url": "https://people.richland.edu/dkirby/141macaddress.htm",
"datetimes": {
"$date": "2021-02-13T02:02:00.000Z"
}
{
"_id": {
"$oid": "5ff539269a10d529d88d19f4"
},
"ip_address": "192.168.0.7",
"mac_address": "00:A0:C9:14:C8:30",
"url": "https://people.richland.edu/dkirby/141macaddress.htm",
"datetimes": {
"$date": "2021-02-12T19:00:00.000Z"
}
}
{
"_id": {
"$oid": "60083d9a1cad2b613cd0c0a2"
},
"ip_address": "192.168.1.5",
"mac_address": "00:0A:05:C7:C8:31",
"url": "www.facebook.com",
"datetimes": {
"$date": "2021-01-24T17:00:00.000Z"
}
}
example query:
BasicDBObject whereQuery = new BasicDBObject();
DBCursor cursor = table1.find(whereQuery);
while (cursor.hasNext()) {
DBObject obj = cursor.next();
String ip_address = (String) obj.get("ip_address");
String mac_address = (String) obj.get("mac_address");
Date datetimes = (Date) obj.get("datetimes");
String url = (String) obj.get("url");
System.out.println(ip_address, mac_address, datetimes, url);
}
in Java, How I can know count duplicated data of "url". And how many of duplicated.
in mongodb you can solve this problem with "Aggregation Pipelines". You need to implement this pipeline in "Mongodb Java Driver". It gives only duplicated results with their duplicates count.
db.getCollection('table1').aggregate([
{
"$group": {
// group by url and calculate count of duplicates by url
"_id": "$url",
"url": {
"$first": "$url"
},
"duplicates_count": {
"$sum": 1
},
"duplicates": {
"$push": {
"_id": "$_id",
"ip_address": "$ip_address",
"mac_address": "$mac_address",
"url": "$url",
"datetimes": "$datetimes"
}
}
}
},
{ // select documents that only duplicates count higher than 1
"$match": {
"duplicates_count": {
"$gt": 1
}
}
},
{
"$project": {
"_id": 0
}
}
]);
Output Result:
{
"url" : "https://people.richland.edu/dkirby/141macaddress.htm",
"duplicates_count" : 2.0,
"duplicates" : [
{
"_id" : ObjectId("5fc8eb07d473e148192fbecd"),
"ip_address" : "192.168.0.1",
"mac_address" : "00:A0:C9:14:C8:29",
"url" : "https://people.richland.edu/dkirby/141macaddress.htm",
"datetimes" : {
"$date" : "2021-02-13T02:02:00.000Z"
}
},
{
"_id" : ObjectId("5ff539269a10d529d88d19f4"),
"ip_address" : "192.168.0.7",
"mac_address" : "00:A0:C9:14:C8:30",
"url" : "https://people.richland.edu/dkirby/141macaddress.htm",
"datetimes" : {
"$date" : "2021-02-12T19:00:00.000Z"
}
}
]
}
If I understand your question correctly you're trying to find the amount of duplicate entries for the field url. You could iterate over all your documents and add them to a Set. A Set has the property of only storing unique values. When you add your values, the ones that are already in the Set will not be added again. Thus the difference of the number of entries in the Set to the number of documents is the amount of duplicate entries for the given field.
If you wanted to know which URLs are non-unique, you could evaluate the return value from Set.add(Object) which will tell you, whether or not the given value has been in the Set beforehand. If it has, you got yourself a duplicate.
I'm trying to learn MongoDB and I want to get a String inside an Object Array, my MongoDB document is here:
{
"_id" : ObjectId("5f1507fed91e81246c409a59"),
"identification" : "punishment",
"lastID" : 2,
"punishmentsTypes" : [
{
"category" : "OFENSA_JOGADOR",
"reason" : "Ofensa a Jogador",
"group" : [
"HELPER",
"MODERATOR",
"ADMINISTRATOR",
"MANAGER",
"MASTER"
],
"description" : "Ofender algum jogador",
"cases" : [
{
"1" : {
"type" : "MUTE",
"duration" : 604800000
}
},
{
"2" : {
"type" : "BAN",
"duration" : 0
}
}
]
},
{
"category" : "FALSIFICACAO",
"reason" : "Falsificação de provas",
"group" : [
"ADMINISTRATOR",
"MANAGER",
"MASTER"
],
"description" : "Falsicar provas ao denunciar um jogador em nosso fórum",
"cases" : [
{
"1" : {
"type" : "BAN",
"duration" : 0
}
}
]
},
{
"category" : "HACK",
"reason" : "Hack",
"group" : [
"MODERATOR",
"ADMINISTRATOR",
"MANAGER",
"MASTER"
],
"description" : "Uso de cheats ou programas ilícitos",
"cases" : [
{
"1" : {
"type" : "BAN",
"duration" : 7776000000.0
}
},
{
"2" : {
"type" : "BAN",
"duration" : 0
}
}
]
}
],
"unpunishmentTypes" : [
{}
]
}
I've tried this:
MongoCollection<Document> collection = mongoDatabase.getCollection("settings");
BasicDBObject query = new BasicDBObject();
BasicDBObject field = new BasicDBObject();
query.put("id", "punish");
field.put("punishmentsTypes", 1);
field.put("_id", 0);
Document test = collection.find(query).projection(field).first();
assert test != null;
Object object = test.get("punishmentsTypes");
System.out.println(object);
And that's the output:
[Document{{category=OFENSA_JOGADOR}},
Document{{category=FALSIFICACAO}}, Document{{category=HACK}}]
How can I get only the category string, to the output be: OFENSA_JOGADOR, FALSIFICACAO, HACK?
I'm not sure how did you get that result with your query but here is how I get your result:
MongoCollection<Document> collection = mongoDatabase.getCollection("settings");
Document query = new Document();
query.put("identification", "punishment");
Document test = collection.find(query).first();
List<Document> punishmentsTypes = test.getList("punishmentsTypes", Document.class);
for (Document document : punishmentsTypes) {
String category = document.getString("category");
System.out.println(category);
}
I have a MongoDB storing data from different sensors. It has the following structure:
{
"_id" : 1,
"sensorName" : "Heart Rate",
"samplePeriod" : 1000,
"data" : [
{
"timestamp" : NumberLong("1483537204046"),
"dataPoints" : [ 68 70 ]
},
{
"timestamp" : NumberLong("1483537206046"),
"dataPoints" : [ 68 70 ]
}
]
}
{
"_id" : 2,
"sensorName" : "Ambient Light",
"samplePeriod" : 500,
"data" : [
{
"timestamp" : NumberLong("1483537204058"),
"dataPoints" : [ 56, 54, 54, 54 ]
},
{
"timestamp" : NumberLong("1483537206058"),
"dataPoints" : [ 56, 54, 54, 54 ]
}
]
}
Now for example i need the "Heart Rate" - document with all of its fields and those of its "data" - subdocuments matching the condition "timestamp between 1483537204000 and 1483537214000".
I already got the answer on how to do this in the mongo shell in another Question. See this code:
aggregate([{
$match: {
"_id": 1
}
}, {
"$project": {
"_id": 1,
"sensorName": 1,
"samplePeriod": 1,
"data": {
"$filter": {
"input": "$data",
"as": "result",
"cond": {
$and: [{
$gte: ["$$result.timestamp", 1483537204000]
}, {
$lte: ["$$result.timestamp", 1483537214000]
}]
}
}
}
}
}])
But how do I do this in java spring-data? It seems there is nothing like $filter in spring-data. Is there a workaround?
How efficient is $filter anyway?
Can you think of a more efficient/practical way of structuring this kind of data in mongodb?
Thanks in advance!
You'll need to make use of MongoTemplate provided in the spring mongo data dependency. There is no out of box support for $filter in the current release version. Make use of AggressionExpression. Include below projection in project. Use 1.8.5 spring mongo data version.
Aggregation aggregation = newAggregation(
match(Criteria.where("_id").is(1)),
project( "_id", "sensorName", "samplePeriod").and(new AggregationExpression() {
#Override
public DBObject toDbObject(AggregationOperationContext aggregationOperationContext) {
DBObject filter = new BasicDBObject("input", "$data").append("as", "result").append("cond",
new BasicDBObject("$and", Arrays.<Object> asList(new BasicDBObject("$gte", Arrays.<Object> asList("$$result.timestamp", 1483537204000L)),
new BasicDBObject("$lte", Arrays.<Object> asList("$$result.timestamp", 1483537214000L)))));
return new BasicDBObject("$filter", filter);
}
}).as("data")
);
List<BasicDBObject> dbObjects = monoTemplate.aggregate(aggregation, "collectionname", BasicDBObject.class).getMappedResults();
I think the same can be achieved by the use of unwind and an extra match. Spring mongo driver does provide support for unwind and it looks bit cleaner.
aggregate([{
$match: {
"_id": 1
}
}, {
$unwind : "$data"
},{
$match : {'data.timestamp' : {$gte : 1483537204000, $lte : 1483537214000}}
}, {
$group : {
_id : $_id,
data : {$push:$data}
}
}])
The Spring Data MongoDB 1.10 RC1 (Ingalls), 2.0 M2 (Kay) releases (as of writing) have added support for $filter and this can be implemented as follows:
Aggregation.newAggregation(Entity.class,
match(Criteria.where("_id").is(1)),
project("sensorName", "samplePeriod")
.and(
filter("data")
.as("item")
.by(
GTE.of(field("item.timestamp"), 1483537204000)
.LTE.of(field("item.timestamp"), 1483537214000)
)
).as("data")
)
"termsrelation" : [
{
"rel": "RT",
"terms": [
{
"objid": "55dc25083d2cbcb8b0dc48c8",
"source": null,
"scopeNote": [
{
"sourceType": "source",
"source": "abc"
}
],
"formated_name": "Milkbuns",
"name": "Milkbuns",
"type": null,
"url": "test.com",
"nodeid": "14050"
},
{
"objid": "552cae1940feb9123e3f5fb6",
"source": null,
"scopeNote": [
{
"sourceType": "source",
"source": "xyz"
}
],
"formated_name": "Milkchocolate",
"name": "Milkchocolate",
"type": null,
"url": "test.com",
"nodeid": "193570"
}
]
}
]
I need to push
{
"sourceType" : "source",
"source" : "def"
}
json to scopeNote object where name = Milkchocolate by java, Please help me out
I tried this query { "$push" : { "termsrelation.$.terms.$.scopeNote" : { "sourceType" : "source" , "source" : "ddd" }}} with search query { "$and" : [ { "id" : "4003"} , { "termsrelation.rel" : "RT"} , { "termsrelation.terms.scopeNote.sourceType" : "source"} , { "termsrelation.terms.scopeNote.source" : "xyz"} , { "termsrelation.terms.name" : "Milk chocolate"}]} but didn't work
Step 1. First get the position for element there which you want to insert
Step 2. You got the position
then use this query
List<BasicDBObject> andQuery2 = new ArrayList<BasicDBObject>();
andQuery2.add(new BasicDBObject("id", id));
andQuery2.add(new BasicDBObject("termsrelation.rel", relation));
andQuery2.add(new BasicDBObject("termsrelation.terms.name", name));
BasicDBObject searchObj2 = new BasicDBObject();
searchObj2.put("$and", andQuery2);
BasicDBObject basicDBObject = new BasicDBObject();
basicDBObject.put("sourceType", type);
basicDBObject.put("source", source);
BasicDBObject updateQuery = new BasicDBObject();
updateQuery.append("$push", new BasicDBObject().append("termsrelation.$.terms."+position+".scopeNote", basicDBObject));
coll.update(searchObj2, updateQuery).getError();
This is my dbcollection in mongodb
{
"_id" : 0,
"name" : "+Anima",
"author" : "MUKAI Natsumi",
"type" : [
"Adventure",
"Fantasy"
],
"chapters" : [
{
"chapterName" : "+Anima 56",
"chapterLink" : "http://...",
"groupTranslate" : "Manga Palace Group",
"dateUpload" : 1359478800000,
"chapterNumber" : 56.0000000000000000,
"images" : [
"img0",
"img1",
"img2",
"img3"
]
},
{
"chapterName" : "+Anima 55",
"chapterLink" : "http://....",
"groupTranslate" : "Manga Palace Group",
"dateUpload" : 1410109200000,
"chapterNumber" : 55.0000000000000000,
"images" : [
"img0",
"img1",
"img2",
"img3"
]
}
]
}
I cannot find list chapter sort by "dateUpload" in mongodb using java code. Please help.
Mongo $aggregation will solve your problem. Below query first $unwind your chapters array and then sort dateUpload
db.collectionName.aggregate({
"$unwind": "$chapters" // unwind breaks the chapters array
}, {
"$sort": {
"chapters.dateUpload": -1 // then seperated chapters array sorted by dateUpload
}
}, {
"$group": {
"_id": "$_id",
"chapters": {
"$push": "$chapters" // group used for grouping chapters array
}
}
}).pretty()
And for converting above query in java code formatt then follow below mongo aggregation java driver code .
Java Driver and Aggregation Framework
This should do it, using aggregate():
db.foo.aggregate( [ { $project: {chapters: 1} },
{ $unwind: "$chapters" },
{ $sort: {"chapters.dateUpload": -1} }
] );
Extract the chapters subdocument with $project, then $unwind it to deconstruct the array and get each element, finally $sort them on dateUpload value (descending, use 1 for ascending order).