I've stored a bunch of data in my database to draw a binary tree in a html canvas
Idx / Name
1 Apple
2 Bee
3 Cafe
4 Diamond
8 East
9 Game
16 Hobby
Here, idx represents the location of items in a binary tree. So the data above looks something like this in a tree
1.Apple
/ \
2.Bee 3.Cafe
/
4.Diamond
/ \
8.East 9.Game
/
16.Hobby
Now, I need to encode that database rows into a json format:
{
id: "1",
name: "Apple",
data: {},
children: [{
id: "2",
name: "Bee",
data: {},
children: [{
id: "4",
name: "Diamond",
data: {},
children: [{
// East/Game/Hobby comes here in the same manner...
}]
}]
},
{
id: "3",
name: "Cafe",
data: {},
children: [] // has no children
}]
}
What I've tried was creating an array of arrays and going through all the values descending order by grab a vale and put it into its parent array and remove it from the array. So, my pseudo code was something like this...
nodeArray = [1,2,3,4,8,9,16]; <-each node is an object with needed data contained.
treeArray = [........] <- arrays with key=>each index / value=>empty
while(nodeArray size is larger than 1) // 1 = the top most value
{
grab the last node from nodeArray
parent_idx = (int)(last one id / 2)
push the last node into the treeArray[parent_idx]
pop the used index
}
Then, I will have treeArray something like this
treeArray = [
1:[2,3]
2:[4]
4:[8,9]
8:[16]
]
...this is not the array-converted binary tree I was looking for.
So, I need to go through treeArray in desc order and relocate them... Yup. I know I'm getting messed up here :( It's getting more complicated and harder to understand.
Would be there more elegant and simpler way to do it? :(
I ended up using javascript and loop through each node and calling the following function
var objlist = {};
function buildTree(id, parent_id, data)
{
if(id in objlist) alert("It already exists!");
objlist[id] = { id: id, data: data, children: [] };
if (parent_id in objlist)
{
objlist[parent_id].children.push(objlist[id]);
}
}
where parent_id is id/2.
Related
I have been populating a chart embed with data from a multidimensional PHP array ($result). When printing the array to JSON (using print json_encode($result, JSON_NUMERIC_CHECK);) i got the following array structure:
[
{
"name":"Array1",
"data":[
1,
2,
3
]
},
{
"name":"Array2",
"data":[
1,
2,
3
]
}
]
I used this array to populate my highcharts in the code below. This used to work just fine but after I changed the setup of my array it will now have to be reworked.
$.getJSON("../data.php", {id: escape(tableName)}, function(json) {
chartOptions.chart1.xAxis.categories = json[0]['data'];
chartOptions.chart1.series[0].data = json[1]['data'];
});
The new setup of my $result array after making some changes is the below:
{
"Array1":{
"data":[
"1",
"2",
"3"
]
},
"Array2":{
"data":[
"1",
"2",
"3"
]
}
}
As such, the code I used to populate my Highcharts no longer works. I would very much appreciate if anyone can help me understand how I can rework the $.getJSON code such that it would work with the new array structure. Or maybe inform me if I have to stick with the old array setup? Thanks.
From what I can tell (haven't tested), you just need to change:
$.getJSON("../data.php", {id: escape(tableName)}, function(json) {
chartOptions.chart1.xAxis.categories = json[0]['data'];
chartOptions.chart1.series[0].data = json[1]['data'];
});
To
$.getJSON("../data.php", {id: escape(tableName)}, function(json) {
chartOptions.chart1.xAxis.categories = json['Array1']['data'];
chartOptions.chart1.series[0].data = json['Array2']['data'];
});
The change in the JSON structure changed from an array of dictionaries, to a dictionary of dictionaries, so you no longer access it via index, instead you access it by key (Array1, Array2).
I have a document in mongodb with 2 level deep nested array of objects that I need to update, something like this:
{
id: 1,
items: [
{
id: 2,
blocks: [
{
id: 3
txt: 'hello'
}
]
}
]
}
If there was only one level deep array I could use positional operator to update objects in it but for second level the only option I've came up is to use positional operator with nested object's index, like this:
db.objects.update({'items.id': 2}, {'$set': {'items.$.blocks.0.txt': 'hi'}})
This approach works but it seems dangerous to me since I'm building a web service and index number should come from client which can send say 100000 as index and this will force mongodb to create an array with 100000 indexes with null value.
Are there any other ways to update such nested objects where I can refer to object's ID instead of it's position or maybe ways to check if supplied index is out of bounds before using it in query?
Here's the big question, do you need to leverage Mongo's "addToSet" and "push" operations? If you really plan to modify just individual items in the array, then you should probably build these arrays as objects.
Here's how I would structure this:
{
id: 1,
items:
{
"2" : { "blocks" : { "3" : { txt : 'hello' } } },
"5" : { "blocks" : { "1" : { txt : 'foo'}, "2" : { txt : 'bar'} } }
}
}
This basically transforms everything in to JSON objects instead of arrays. You lose the ability to use $push and $addToSet but I think this makes everything easier. For example, your query would look like this:
db.objects.update({'items.2': {$exists:true} }, {'$set': {'items.2.blocks.0.txt': 'hi'}})
You'll also notice that I've dumped the "IDs". When you're nesting things like this you can generally replace "ID" with simply using that number as an index. The "ID" concept is now implied.
This feature has been added in 3.6 with expressive updates.
db.objects.update( {id: 1 }, { $set: { 'items.$[itm].blocks.$[blk].txt': "hi", } }, { multi: false, arrayFilters: [ { 'itm.id': 2 }, { 'blk.id': 3} ] } )
The ids which you are using are linear number and it has to come from somewhere like an additional field such 'max_idx' or something similar.
This means one lookup for the id and then update. UUID/ObjectId can be used for ids which will ensure that you can use Distributed CRUD as well.
Building on Gates' answer, I came up with this solution which works with nested object arrays:
db.objects.updateOne({
["items.id"]: 2
}, {
$set: {
"items.$.blocks.$[block].txt": "hi",
},
}, {
arrayFilters: [{
"block.id": 3,
}],
});
MongoDB 3.6 added all positional operator $[] so if you know the id of block that need update, you can do something like:
db.objects.update({'items.blocks.id': id_here}, {'$set': {'items.$[].blocks.$.txt': 'hi'}})
db.col.update({"items.blocks.id": 3},
{ $set: {"items.$[].blocks.$[b].txt": "bonjour"}},
{ arrayFilters: [{"b.id": 3}] }
)
https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#update-nested-arrays-in-conjunction-with
This is pymongo function for find_one_and_update. I searched a lot to find the pymongo function. Hope this will be useful
find_one_and_update(filter, update, projection=None, sort=None, return_document=ReturnDocument.BEFORE, array_filters=None, hint=None, session=None, **kwargs)
Added reference and pymongo documentation in comments
I have this JSON, I'm parsing. I can retrieve all the values of field_data in order in PHP, but I need to traverse and get the values I wan't by specifying the field name, without concern for order:
JSON
{
created_time: "2018-05-14T16:11:02+0000",
id: "555555555555",
field_data: [
{
name: "bedrooms_interested_in?",
values: [
"2"
]
},
{
name: "When_are_you_looking?",
values: [
"January 1s 2019"
]
},
{
name: "email",
values: [
"xxxx#domain.com"
]
},
{
name: "full_name",
values: [
"John Michael"
]
},
{
name: "phone_number",
values: [
"+15555555555"
]
}
]
}
PHP
This is grabbing the last 3 fields. I'm currently able to pull the fields_data in order like this, but how could I grab the value fields I want by specifying the name field I'm looking for?
$data = json_decode($response, true);
// var_dump($data);
file_put_contents('dump.txt', $response);
$lead_email = $data['field_data'][2]['values'][0];
$lead_fullname = $data['field_data'][3]['values'][0];
$lead_phone = $data['field_data'][4]['values'][0];
You can use array_column to re-index an array by a given column, which will give you easier and more reliable access to the data:
$data['field_data'] = array_column($data['field_data'], null, 'name');
This allows you to access fields by name instead of their numeric index, e.g.
echo $data['field_data']['email']['values'][0];
// xxxx#domain.com
See https://eval.in/1003874 for a full example
(Note, I added some quotes to your JSON property names, since they were missing in the question. I assume that's a formatting issue, since this wouldn't work at all otherwise)
I have an object saved in the variable called items.
0: Object
name: "Jim"
age: "42"
1: Object
name: "Bill"
age: "50"
When trying to post
$.post("mypage.php", items, function(data)
I get an empty post variable in the php page, but this returns post variables
$.post("mypage.php", "name=jim", function(data)
What am I doing wrong?
Edit it is an array of objects so if I pass
$.post( "mypage", items[0], function( data) {
I get a results but
$.post( "mypage", items, function( data) {
print_r is empty
It looks like the object you're posting may be an array with this format:
items = [
{
name: "Jim",
age: "42"
},
{
name: "Bill",
age: "50"
}
]
The docs seem to indicate that you must pass a plain object. You probably want to post something with the format:
items = {
people: [
{
name: "Jim",
age: "42"
},
{
name: "Bill",
age: "50"
}
]
};
Then you should be able to access the data via $_POST['people'].
UPDATE
To be accurate, you can post your array just fine, it will generate this post Jim=&Bill=
Almost surely not what you want. However if you follow the syntax specified by jQuery.param, your array will be treated correctly. Should be and array of objects with name and value:
items = [
{
name: "Jim",
value: "42"
},
{
name: "Bill",
value: "50"
}
]
You are using a curious behaviour of jQuery. It's found in the $.param function, which is used behind the scenes to prepare an AJAX query from your data.
If you send an array, jQuery expects it to be an array of objects, each of which has two keys, name and value. You are obviously not providing data in that structure. Your script actually sends data that looks like this:
Jim=undefined&Bill=undefined
If you do print_r($_POST['Jim']); in PHP, you will get the string undefined.
You obviously don't want this. You need to send the array within an object.
{
people: [
{
name: 'Jim',
age: 42
},
{
name: 'Bill',
age: '50'
}
]
}
This way your data will be serialised as this:
people[0][name]=Jim&people[0][value]=42&people[1][name]=Bill&people[1][age]=50
If you do print_r($_POST['people']);, you will get a meaningful result.
I have this simple jQuery function:
$(document).ready(function () {
var books = {};
books.id = '1';
books.author = 'Bob';
$.post('/index.php',
{
books: books
},
function(data, textStatus)
{
alert(data);
});
});
And this index PHP script:
<?php
foreach($_POST['books'] AS $key) {
echo ''.$key['id'].' is written by '.$key['author'].'';
}
?>
I want to loop through the jQuery array and display the id and author of each key in the array. I don't know the correct way to access the values in the array. It seems I'm doing it wrong.
You have misunderstood the difference between {} and [] in JavaScript:
{} is an object
[] is an array
In your case you should pass an array of book objects for this to work in your php script.
Example:
var books = [
{
id: 1,
name: "The Da Vinci Code",
author: "Dan Brown"
},
{
id: 1,
name: "Gray Mountain: A Novel",
author: "John Grisham"
}
]
To add more elements to the array after it has been initialized, you can simply use push:
books.push({id: 3, name: "Avatar", author: "Lisa Fitzpatrick"});
Will output:
1 is written by Dan Brown
2 is written by John Grisham
3 is written by Lisa Fitzpatrick