I have uploaded the following JSON file into a mongoDB database:
https://cloudpricingcalculator.appspot.com/static/data/pricelist.json
I have succeeded in accessing it using the following line in my app.js:
db.googlepricelist.find({},
{"gcp_price_list":1}).pipe(JSONStream.stringify()).pipe(res);
I would like to query all objects in object gcp_price_list, where the name of the object contains substring "VMIMAGE".
So for example bellow objects:
"CP-COMPUTEENGINE-VMIMAGE-F1-MICRO"
"CP-COMPUTEENGINE-VMIMAGE-G1-SMALL"
I can't figure out how to define a query which is able to do this.
So far I tried this:
db.googlepricelist.find({$where: function() {
for (var key in this.gcp_price_list) {
if (key.indexOf("VMIMAGE")!=-1) {
return true;
}
return false;
}
},}).pipe(JSONStream.stringify()).pipe(res);
This should get you going and works from v3.4.4 onwards:
db.googlepricelist.aggregate({
$project: {
"gcp_price_list_as_array": { $objectToArray: "$gcp_price_list" }, // transform "gcp_price_list" into an array of key-value pairs
}
}, {
$unwind: "$gcp_price_list_as_array" // flatten array
}, {
$match: { "gcp_price_list_as_array.k": /VMIMVAGE/ } // like filter on the "k" (as in "key") field using regular expression
})
You'd normally attempt to use $filter to filter the array which, however, doesn't work using a regular expression. There's an open JIRA ticket for that but it's simply not yet available.
Related
The data being used is:
{
'name':'Arsenal FC',
'squad':[
{
'id':'3174',
'name':'Bernd Leno',
'position':'Goalkeeper',
'dateOfBirth':'1992-03-04',
'nationality':'Germany',
'role':'PLAYER'
},
{
'id':'7778',
'name':'Petr Čech',
'position':'Goalkeeper',
'dateOfBirth':'1982-05-20',
'nationality':'Czech Republic',
'role':'PLAYER'
},
{
'id':'7780',
'name':'Deyan Iliev',
'position':'Goalkeeper',
'dateOfBirth':'1995-02-25',
'nationality':'FYR Macedonia',
'role':'PLAYER'
}
]
}
I am trying to return a single player object like below:
{
'id':'7778',
'name':'Petr Čech',
'position':'Goalkeeper',
'dateOfBirth':'1982-05-20',
'nationality':'Czech Republic',
'role':'PLAYER'
}
I am using mongodb, the query being used is {"squad.id": id} with id coming from the user input however, this returns the entire dataset. How do I get it to return a single player?
MongoDB does allow querying nested object property in an array, but not project only a particular element of an array.
But instead if you wish to, you use can aggregate query rather than find, and use $indexOfArray to find the index of element in array based on expression, and then further project only that item using $arrayElementAt
I need to find a way to auto-increment the "Bill_id" field by 1 , whenever I insert a new item to a nested array in a collection:
this is the structure of the nested document
I also found this demo on the official documentation :
https://docs.mongodb.com/v3.0/tutorial/create-an-auto-incrementing-field/
function getNextSequence(name) {
var ret = db.counters.findAndModify(
{
query: { _id: name },
update: { $inc: { seq: 1 } },
new: true
}
);
return ret.seq;
}
but I didn't know how to use the solution because it's proposing a JavaScript function that does all the work
However I am working with python script , and to be specific a REST API using flask
Write a similar function mentioned in the docs, in python. This is what I use.
def getLastUserId(self):
if len(list(self.find())) is not 0:
last_user = list(self.find({}).sort("user_id", -1).limit(1))
return last_user[0]["user_id"]
else:
return 0
This will return the "user_id" of the last added document. Just increment it by one, and do a simple insert for the new document.
I have some JSON which I have in a object but I can seem to return the values a sample of the json is as follows.
{
"rootLayout":"main",
"layoutDescriptions":[
{
"id":"main",
"container" : {
"type":"Tabs",
"content":[
{
"type":"Panel",
"label":"Simple Address",
"layout":"SimpleForm",
"comment":"This form is simple name value pairs",
"content":[
{ "type":"label", "constraint":"newline", "text":"Org Name" },
{ "type":"text", "property":"propOne" },
{ "type":"label", "constraint":"newline", "text":"Address" },
{ "type":"text", "property":"addrLine1" },
{ "type":"text", "property":"addrLine2" },
{ "type":"text", "property":"addrLine3" },
{ "type":"label", "constraint":"newline", "text":"Postcode" },
{ "type":"text", "property":"postcode" }
]
},
I am trying to return the rootLayout using
obj[0].rootLayout.id
This doesn't work also I am wondering how to access the content elements.
I am new to json and I have been thrown in the deep end I think. I cannot find any good reading on the internet can anyone recommend some.
Thanks.
Some explanation because you don't seem to understand JSON
It's not as complicated as one may think. It actually represents javascript objects as if they'd be written by code.
So if you have JSON written as:
{
id : 100,
name: "Yeah baby"
}
This means that your object has two properties: id and name. The first one is numeric and the second one is string.
In your example you can see that your object has two properties: rootLayout and layoutDescriptions. The first one jsonObj.rootLayout is string and will return "main" and the second one is an array:
layoutDescriptions: [ {...}, {...},... ]
Apparently an array of objects because array elements are enclosed in curly braces. This particular array element object that you provided in your example has its own properties just like I've explained for the top level object: id (string), container (another object because it's again enclosed in curlies) etc...
I hope you understand JSON notation a bit more.
So let's go to your question then
You can get to id by accessing it via:
jsonObj.layoutDescriptions[0].id
and further getting to your content objects:
var contentObjects = jsonObj.layoutDescriptions[0].container.content[0].content;
for(var i = 0; i < contentObjects.length, i++)
{
// assign this inner object to a variable for simpler property access
var contObj = contentObjects[i];
// do with this object whatever you need to and access properties as
// contObj.type
// contObj.property
// contObj.text
// contObj.constraint
}
Mind that this will only enumerate first content object's content objects... If this makes sense... Well look at your JSON object and you'll see that you have nested content array of objects.
The object is an object, not an array, and it doesn't have a property called 0.
To get rootLayout:
obj.rootLayout
However, rootLayout is a string, not an object. It doesn't have an id. The first item in the layoutDescriptions array does.
obj.layoutDescriptions[0].id
Are you trying to get one of layoutDescriptions with id equals to obj.rootLayout?
var targetLayout = {};
for(var i = 0; i < obj.layoutDescriptions.length; i++) {
if(obj.layoutDescriptions[i].id == obj.rootLayout) {
targetLayout = obj.layoutDescriptions[i]; break;
}
}
console.log(targetLayout);
I would like to achieve something like this:
filteringSelect.query = {id: "12|13"};
or
filteringSelect.query = {id: new RegExp("12|13")};
Is it possible?
I am using ItemFileReadStore as a store for that FilteringSelect.
See Fuzzy Matches on dijit.form.ComboBox / dijit.form.FilteringSelect Subclass if you want to go the extra mile. This is however for filtering user-input.
For filtering away entries before opening/entering anything in the filteringSelect, continue what youre doing allready. A simple string will not accept the OR operator though, use RegExp.
ItemFileReadStore docs on query
var store = new ItemFileReadStore( {
query: {
id: new RegExp("/^(12|13)$/")
}
} );
As a starting point, ALL items are present in the store, the way to make use of the queryengine is through fetch
store.fetch({
query: {
// yes, you can set the query property directly
// in the store and leave out this parameter
id: new RegExp("^(1|12)$")
},
onComplete: function(items) {
dojo.forEach(items, function(item) {
console.log(store.getValue(item, 'name'))
});
}
})
See http://jsfiddle.net/LuUbT/ for example usage
It sounds a lot more complicated than it really is.
So in Perl, you can do something like this:
foreach my $var (#vars) {
$hash_table{$var->{'id'}} = $var->{'data'};
}
I have a JSON object and I want to do the same thing, but with a javascript associative array in jQuery.
I've tried the following:
hash_table = new Array();
$.each(data.results), function(name, result) {
hash_table[result.(name).extra_info.a] = result.(name).some_dataset;
});
Where data is a JSON object gotten from a $.getJSON call. It looks more or less like this (my JSON syntax may be a little off, sorry):
{
results:{
datasets_a:{
dataset_one:{
data:{
//stuff
}
extra_info:{
//stuff
}
}
dataset_two:{
...
}
...
}
datasets_b:{
...
}
}
}
But every time I do this, firebug throws the following error:
"XML filter is applied to non-xml data"
I think you can use the JSON response as an associative array. So you should be able to go directly in and use the JSON.
Assuming you received the above example:
$('result').innerHTML = data['results']['dataset_a']['dataset_two']['data'];
// Or the shorter form:
$('result').innerHTML = data.results.dataset_a.dataset_two.data;
Understand that I haven't tested this, but it's safer to use the square brackets with a variable than it is to use parenthesis plus the name with the dot accessor.
Your example is failing because of some convoluted logic I just caught.
$.each(data.results), function(name, result) {
hash_table[result.(name).extra_info.a] = result.(name).some_dataset;
});
Now, the foreach loop goes through the variable data.results to find the internal elements at a depth of 1. The item it finds is given to the lambda with the key of the item. AKA, the first result will be name = "datasets_a" item = object. Following me so far? Now you access the returned hash, the object in item, as though it has the child key in name ... "datasets_a". But wait, this is the object!
If all else fails... write your result JSON into a text field dynamically and ensure it is formatted properly.
Why would you want to change an array into another array ?-)
-- why not simply access the data, if you want to simplify or filter, you can traverse the arrays of the object directly !-)
This works. Just dump it into a script block to test.
d = {
'results':{
'datasets_a':{
'dataset_one':{
'data':{
'sample':'hello'
},
'extra_info':{
//stuff
}
},
'dataset_two':{
///
}
///
},
'datasets_b':{
///
}
}
}
alert(d.results.datasets_a.dataset_one.data.sample)
I hope this pasted in correctly. This editor doesn't like my line breaks in code.
d = {
'results':{
'datasets_a':{
'dataset_one':{
'data':{
'sample':'hello'
},
'extra_info':{
//stuff
}
},
'dataset_two':{
///
}
///
},
'datasets_b':{
///
}
}
};
alert(d.results.datasets_a.dataset_one.data.sample)