Using Morphia, is it possible to perform a saveOrUpdate / upsert operation on an object embedded inside an array.
Consider the following document :
{
_id : "abcd",
myArray : [{
"key" : "areaTotal",
"value" : "101.9",
"label" : "Total area (municipality)"
}, {
"key" : "areaUrban",
"value" : "803",
"label" : "Total area (urban)"
}, {
"key" : "populationDensity",
"value" : "15991",
"label" : "Population desnsity"
}
]
}
Is there a clean way to replace for example array element with key "areaUrban" by another object
such as
{
"key" : "areaUrban",
"value" : "123",
"label" : "a new label"
}
For now I do it in two update operations first delete, then add :
UpdateOperations<T> ops = createUpdateOperations().removeAll("myArray ", new BasicDBObject("key", "areaUrban"));
update(createQuery().field("_id").equal(myObjId),ops);
UpdateOperations<T> ops2 = createUpdateOperations().add("myArray ", myReplacementObject);
update(createQuery().field("_id").equal(myObjId),ops2);
Which works fine but can I do it in only one update op (either with morphia or with plain mongo java driver) ?
Also if a matching object did not originally exist in the array, then the myReplacementObject object should just be added to the array.
thanks
With the $ positional operator:
db.test.update({_id: "abcd", "myArray.key": "areaUrban"}, {$set: {"myArray.$.value": 123, "myArray.$.label": "a new label"}})
[Edit] As JohnnyHK mentions in the comments this won't upsert the nested document if it doesn't exist.
Related
This is JSON that I want to use for a search:
{
"_index" : "test", "_type" : "insert", "_id" : "3",
"_version" : 2, "found" : true,
"_source" : {
"ACCOUNT_ID" : "123",
"CONTACT_ID" : "ABC"
}
}
How do I search for all the JSON which have ACCOUNT_ID starting from 1?
You can use Wildcard in elasticsearch to search for an ACCOUNT_ID which starts from 1
GET index/_search
{
"query": {
"wildcard": {
"ACCOUNT_ID ": {
"value": "1*"
}
}
}
}
In Java, you can try something like this:
QueryBuilders.wildcardQuery("ACCOUNT_ID ", "1*");
From what i see in your comments you are trying to find id's starting with 1 for example. Well if your analyzer is the standard one the id "123" is tokenized like "123". You can use wildcard and search like '1*'. Be careful using wildcards cause it takes some memory.
See here: QueryString - Wildcard
So I have a few dbobjects in my mongo database. Here's an example of one of the objects:
{ "_id" : { "$oid" : "525b048580c3fb0d62d2b6fc"} , "city" : "London" , "currentWeather" : [ { "cloudcover" : "25" , "humidity" : "82" , "observation_time" : "08:37 PM" , "precipMM" : "0.0" , "pressure" : "1008" , "temp_C" : "11" , "temp_F" : "52" , "visibility" : "10" , "weatherCode" : "113" , "weatherDesc" : [ { "value" : "Clear"}] , "weatherIconUrl" : [ { "value" : "http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0008_clear_sky_night.png"}] , "winddir16Point" : "W" , "winddirDegree" : "280" , "windspeedKmph" : "19" , "windspeedMiles" : "12"}]}
Now, I need to get all the dbobjects in my database whose value is lower than a given "temp_C", I have used something like this:
BasicDBObject query = new BasicDBObject("temp_C", new BasicDBObject(">", graden));
But it's failing, and I think it is because the property is a subproperty of "currentWeather", yet I have no idea how to address this problem. I am using java to do this.
Looking at your document structure, you're trying to access a subdocument that lives inside an array in your document, so it's a bit more complicated than a standard query:
{ "_id" : { "$oid" : "525b048580c3fb0d62d2b6fc"} , <-- Document
"city" : "London" ,
"currentWeather" : [ <-- Array
{ "cloudcover" : "25", <-- Sub document
...etc...
"pressure" : "1008" ,
"temp_C" : "11",
"temp_F" : "52",
...etc...
}
]
}
In order to get to the nested object, you need to reference its position in the array (in this case, it's zero as it's the first element in the array) and then the field name in the sub document. So your query looks like this:
BasicDBObject query = new BasicDBObject("currentWeather.0.temp_C",
new BasicDBObject("$gt", 11));
Note you had two problems in your original query:
1) You need to reference currentWeather.0.temp_C
2) Your gt operator needs to start with a dollar sign not an ampersand.
Also, you said you wanted the query to return values lower than a given value, in which case you probably want $lt not $gt.
You can't directly use the value of the object of an array in a query. You can use aggregate framework of Mongo. Java Docs For Aggregate are here
Platform: MongoDB, Spring, SpringDataMongoDB
I have a collection called "Encounter" with below structure
Encounter:
{ "_id" : "49a0515b-e020-4e0d-aa6c-6f96bb867288",
"_class" : "com.keype.hawk.health.emr.api.transaction.model.Encounter",
"encounterTypeId" : "c4f657f0-015d-4b02-a216-f3beba2c64be",
"visitId" : "8b4c48c6-d969-4926-8b8f-05d2f58491ae",
"status" : "ACTIVE",
"form" :
{
"_id" : "be3cddc5-4cec-4ce5-8592-72f1d7a0f093",
"formCode" : "CBC",
"fields" : {
"dc" : {
"label" : "DC",
"name" : "tc",
},
"tc" : {
"label" : "TC",
"name" : "tc",
},
"notes" : {
"label" : "Notes",
"name" : "notes",
}
},
"notes" : "Blood Test",
"dateCreated" : NumberLong("1376916746564"),
"dateModified" : NumberLong("1376916746564"),
"staffCreated" : 10013,
"staffModified" : 10013
},
}
The element "fields" is represented using a Java Hashmap as:
protected LinkedHashMap<String, Field> fields;
The Key to the hashmap () is not fixed, but generated at run time.
How do I query to get all documents in the collection where "label" = "TC"?
It's not possible to query like db.encounter.find({'form.fields.dc.label':'TC'}) because the element name 'dc' is NOT known. I want to skip that postion and the execute query, something like:
db.encounter.find({'form.fields.*.label':'TC'});
Any ideas?
Also, how do I best use indexes in this scenario?
If fields were an array and your key a part of the sub-document instead:
"fields" : [
{ "key" : "dc",
"label" : "DC",
"name" : "dc"
},
{ "key" : "tc",
"label" : "TC",
"name" : "tc"
}
]
In this case, you could simply query for any sub-element inside the array:
db.coll.find({"form.fields.label":"TC"})
Not sure how you would integrate that with Spring, but perhaps the idea helps? As far as indexes are concerned, you can index into the array, which gives you a multi-key index. Basically, the index will have a separate entry pointing to the document for each array value.
I'm trying to fetch records within a specific radius in km/miles.
mongodb 2d index:
db.collection.ensureIndex({locaction:"2d"})
a record in the collection has the indexed key:
"location" : { "longitude" : 34.791592164168, "latitude" : 32.0516908 0405 }
Calling collection's getIndexes() from shell gives me this:
...{
"v" : 1,
"key" : {
"location" : "2d"
},
"ns" : "events.events",
"name" : "location_2d"
}...
despite all the above, trying to fetch records with this command fails:
> db.events.find({location:{ $near :{ longitude:34,latitude:32},$maxDistance:10 / 3963.192}})
anyone can point out what prevent this from working?
AFAIK, $near takes an array of the two target values, so you can try giving your values in array: -
db.events.find({location:{ $near : [34, 32],$maxDistance:10 / 3963.192}})
I pass out a ajax get which contains a parameter i.e. date added to db.
Java queries the DB for results of persons added on this date, and builds a JSON object for me like so:
{
"resultdata" : { "rowsReturned" : "2", "fetchTime" : "180"}
"row_1" : { "name" : "Larry", "sex" : "m", "age" : "26", "location" : "seattle" }
"row_2" : { "name" : "Pedro", "sex" : "m", "age" : "22", "location" : "unknown" }
}
I can then return the JSON object as a String. I'd then like to dynamically build a table based on these results.
First of all is the JSON object correct for building a table?
The result data tells me how many rows and the time taken in milliseconds, followed by however many rows in that particular format.
I then want to create a table inside a specific div element once these results are returned to my browser on the fly with no page refreshes etc.
so Id expect Table headers with titles of each column - followed by you guessed it 2 rows.
How is the best way to go about doing this. I am familiar with jQuery, JSON is totally new to me and dealing with JSON in jQuery is something i'm keen on learning.
Any help is much appreciated.
you can use jsonlint to validate your json.
Yours is not valid. It's missing some ',':
{
"resultdata" : {
"rowsReturned" : "2",
"fetchTime" : "180"
}, // <--
"row_1" : {
"name" : "Larry",
"sex" : "m",
"age" : "26",
"location" : "seattle"
}, // <--
"row_2" : {
"name" : "Pedro",
"sex" : "m",
"age" : "22",
"location" : "unknown"
}
}
I've made a little DEMO of one possible way how to loop through the json with for-in-loops
for (key in json) {
loops through the json and stores each key in the 'key' variable.
in your case 'resultdata','row_1','row_2'.
So to access the data for each key you write json[key] which translates to json['row_1'] for example.
Now you do the same thing for the row_1 object with:
for(key1 in json[key])
key1 are now the keys in the row_1 object: 'name','sex',...
to access the data now you'll write json[key][key1] which would be json['row_1']['name'] for example.
of course it's advisable to give the keys meaningful names to avoid confusion like in my example:)
Your JSON looks fine for building a table.
You'll want to use $.getJSON() to fetch the JSON data, as it will automatically parse the JSON into an object for you. If you need the advanced features of $.ajax(), you can call $.parseJSON() on the returned data from the AJAX call and it will parse the JSON into an object.