How to convert String to Array in MongoDB? - javascript

I'm stuck at the situation when the type of an object was changed.
How can I convert this:
{
"_id" : NumberLong(257),
"address" : "street Street, house 50, appartment 508, floor 5"
}
to this:
{
"_id" : NumberLong(257),
"userAddressList" : [{
"street" : "Street",
"house" : "50",
"building" : "",
"appartment " : NumberLong(508),
"entrance" : NumberLong(0),
"floor" : NumberLong(5),
"intercom" : ""
}]
}
using mongo shell?
I need to convert about 350 entries, hope it can be done by the script.

You could try this:
db.collection.find().forEach( function (x) {
lines = x.address.split(",");
obj = {};
userAddressList = [];
lines.forEach( function (address){
addressArray = address.replace(/^\s\s*/, '').replace(/\s\s*$/, '').split(" ");
obj[addressArray[0]] = !isNaN(parseInt(addressArray[1])) ? parseInt(addressArray[1]) : addressArray[1];
});
obj.building = "";
obj.intercom = "";
userAddressList.push(obj);
x.userAddressList = userAddressList; // convert field to string
db.collection.save(x);
});

you can use a foreach in the update like this
db.test.find( { } ).forEach( function (x) {
x.userAddressList = x.address.split(" ");
db.test.save(x);
});

Related

Duplicate entire array if an object of the array contains multiple comma seperated values in Javascript

I have an nested array with objects docs, which I first flatten to one level.
And I have another flat array called multiValueSelected.
Now I'd like to iterate through all objects of the flattened docs-array and check if the key is also in the multiValueSelected-array.
If so, I would like to copy the entire docs-array for every comma separated value for the specific key, copy all other objects and add the new doc to the table.
With this following approach, I'm able to iterate through all comma separated values, but how can I duplicate the entire docs-array? Thank you for your help.
Example Arrays:
docs [{"id" : "test1", "color" : "green,blue,grey", "size" : "s,m"}, {"id" : "test2", "color" : "green", "size" : "l"}...]
multiValueSelected {"color, size, ..."}
Expected result for data:
1. {"id" : "test1", "color" : "green", "size" : ""}
2. {"id" : "test1", "color" : "blue", "size" : ""}
3. {"id" : "test1", "color" : "grey", "size" : ""}
4. {"id" : "test1", "color" : "", "size" : "s"}
5. {"id" : "test1", "color" : "", "size" : "m"}
6. {"id" : "test2", "color" : "green", "size" : "l"}
Script:
function importTableau(docs, table) {
var data = [];
var importedDocs = 0;
for (var i = 0; i < docs.length; i++) {
var flatten = objectFlattenData(docs[i])
var rec = {}
for (var key in flatten) {
// var key deiines the KEY
// var flatten[key] defines the VALUE without duplicates
// var flatten defines the CURRENT DOCUMENT
if (multiValueSelected.indexOf(key) > -1) {
//console.log('key: ', key, ' flatten: ', flatten[key])
var flattenString = flatten[key];
var id = key.replace(/[^A-Za-z0-9_]+/g, '')
// handling multivalues as seperate doc per value
var properties = flattenString.split(',');
var propertiesLength = properties.length;
for (var i = 0; i < propertiesLength; i++) {
// Trim the excess whitespace.
properties[i] = properties[i].replace(/^\s*/, "").replace(/\s*$/, "");
// Get the single Value
var singleValue = properties[i]
console.log(singleValue);
rec[id] = flatten[singleValue];
data.push(rec);
}
return false;
} else {
// not selected for handling multivalues as seperate doc
var id = key.replace(/[^A-Za-z0-9_]+/g, '')
rec[id] = flatten[key];
};
};
data.push(rec);
};
table.appendRows(data);
It seems a little confusing your expected output, but maybe this is what you want?
let docs = [{
"id": "test1",
"color": "green,blue,grey",
"size": "s,m"
}, {
"id": "test2",
"color": "green",
"size": "l"
}];
let multiValueSelected = ["color", "size"];
let data = [];
for (selected_value of multiValueSelected) {
for (doc of docs) {
if (doc.hasOwnProperty(selected_value)) {
let values = doc[selected_value].split(',');
for (value of values) {
let obj = {id: doc.id};
let keys = Object.keys(doc).filter(k => !['id', selected_value].includes(k));
keys.map(k => obj[k] = '');
obj[selected_value] = value;
data.push(obj);
}
}
}
}
console.log(data)
I really have not understand the question, but if you want to have this:
Input: docs [{"id" : "test1", "color" : "green,blue,grey", "size" : "s,m"}, {"id" : "test2", "color" : "green", "size" : "l"}...]
Output: multiValueSelected ["color, size, ...", "...."]
as an output you can't have [{"color, size, ..."}] because is not a valid json, a json is a composition of key-value pair and not just only a string
You can do this:
const docs = [{"id" : "test1", "color" : "green,blue,grey", "size" : "s,m"}, {"id" : "test2", "color" : "green", "size" : "l"}...];
const multiValueSelected = [];
docs.forEach(doc => {
let currentValue = "";
Object.keys(doc).forEach(key => {
if(doc[key].split(',').length > 1)
currentValue = (currentValue === "") ? key : ", " + key;
}
if(currentValue !== "") multiValueSelected.push(currentValue);
}
if you want as output this [{"color": "green,blue,grey" , "size" : "s,m" }, {"....": "....", ....}]
const docs = [{"id" : "test1", "color" : "green,blue,grey", "size" : "s,m"}, {"id" : "test2", "color" : "green", "size" : "l"}...];
const multiValueSelected = [];
docs.forEach(doc => {
const currentValue = {};
Object.keys(doc).forEach(key => {
if(doc[key].split(',').length > 1)
currentValue[key] = doc[key];
}
if(Object.keys(currentValue).length > 0) multiValueSelected.push(currentValue);
}
please let me know if I have not responded to your question

get all data from firebase

I just started to use firebase and I am new to the node.js environment
im trying to send to get data from my database i got this using this code
var country = sessionStorage.countryname;
var ref = firebase.database().ref('posts/country/' + country + '/')
ref.on('value', function(snapshot) {
snapshot.forEach(function(keysSnapshot) {
var keys = keysSnapshot.val();
console.log('keys', keys);
})
});
I got all the data in keys but i dont know how to access it for example i want to get the age and first_name of each post ..this is what i get in console log
And this is my database
this is the json code
{
"country" : {
"Algeria" : {
"844kh2QXDHgw7i4KBvULpCSO5KE2" : {
"-L9MvZxV2bVjcuKGZx-2" : {
"age" : "26",
"first_name" : "jack",
"gender" : "female",
"home_adress" : "2222222222222222222222222222",
"last_name" : "anonyo",
},
"-L9Mvpnyx1f9DDDygJcG" : {
"age" : "29",
"first_name" : "jazmine",
"gender" : "female",
"home_adress" : "2222222222222222222222222222",
"last_name" : "anony",
}
},
"QgWbVLqInga3JRNuzzlZBCzwkws2" : {
"-L9ES58GkQcZGywqpIWY" : {
"age" : "29",
"first_name" : "jazmine",
"gender" : "female",
"home_adress" : "2222222222222222222222222222",
"last_name" : "anony",
}
}
},
"england" : {
"jdL079kwJUQSBzKE7aNIPInPEHX2" : {
"-L925-sxlxsF5k9LZFHp" : {
"age" : "29",
"first_name" : "jessica",
"gender" : "female",
"home_adress" : "2222222222222222222222222222",
"last_name" : "anony",
}
}
}
}
}
ok this is how i got it working var country = sessionStorage.countryname;
database.ref('posts/country/'+country).once('value').then(function(snapshot) {
var country = snapshot.key ;
snapshot.forEach(function(snapshot1) {
console.log(snapshot1.key); //
snapshot.forEach(function(snapshot2) {
console.log(snapshot2.key); //
snapshot2.forEach(function(snapshot3) {
console.log(snapshot3.key);
console.log(snapshot3.val().first_name)
});
});
});
});
thanks to frank answer here How to retrieve nested child value in Firebase database using javaScript?
ty for the help guys
Get it with snapshot.val()[844kh2QXDHgw7i4KBvULpCSO5KE2][-L9MvZxV2bVjcuKGZx-2][age]. See documentation Read and Write Data on the Web
var starCountRef = firebase.database().ref('posts/' + postId + '/starCount');
starCountRef.on('value', function(snapshot) {
updateStarCount(postElement, snapshot.val());
});
If you want to iterate all your users:
var objectKeys = Object.keys(keys);
for(x=0; x < objectKeys.length; x++){
var currentKey = objectKeys[x];
var userData = keys.currentKey; //Here you have all the data
console.log(userData);
//Now access the first_name property
var firstName = userData.first_name;
}
I have no test it but it should work.

Is there any javascript library to represent json-result of #JsonIdentityInfo?

I have 2 bi-directional models and I use JsonIdentityInfo to prevention from infinite Recursion in json result. Here is my viewmodels:
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class GroupsViewModel extends BaseEntityViewModel<Long> {
private String title;
private Set<UserViewModel> users;
}
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class UserViewModel extends BaseEntityViewModel<Long> {
private String username;
private String password;
private Set<GroupsViewModel> groups;
}
and a part of my json result is like below:
[{
"id" : 1,
"title" : "adminGroup",
"users" : [{
"id" : 1,
"username" : "admin",
"password" : "...",
"groups" : [1]
}, {
"id" : 31,
"username" : "user78",
"password" : "...",
"groups" : [1]
}, {
"id" : 3,
"username" : "ali",
"password" : "...",
"groups" : [{
"id" : 2,
"title" : "newsWriterGroup",
"users" : [{
"id" : 14,
"username" : "staff1",
"password" : "...",
"groups" : [{
"id" : 1005,
"title" : "FileManagerAccessGroup",
"users" : [{
"id" : 25,
"username" : "test1",
"password" : "...",
"groups" : [1005, {
"id" : 1006,
"title" : "noAccessGroup",
"users" : [25, {
"id" : 26,
"username" : "test5",
"password" : "...",
"groups" : [1006]
}
]
}
]
}, 14]
}, 2]
}, ...
As shown in above, if object is repetitive in json result, Jackson put only it's identifier of it. Now I want to know Is there any javascript/jquery library to represent json-result of #JsonIdentityInfo? for example, when javascript/jquery library arrive at 1005 identifier , it automaticaly load group object with id = 1005.
It's very unlikely that such a targeted library exists. You could easily write a function though that deconstructs the data back into an array of users and groups by using typeof checking, and then using recursion when a new object is encountered in the groups or users attributes.
Just be careful when printing out the results that you don't create a circular reference. See this question for help on that.
function Group(group) {
this.id = group.id;
this.title = group.title;
this.users = [];
Group.cache[this.id] = this;
group.users.forEach(this.addUser, this);
}
Group.cache = {};
Group.prototype.addUser = function(user) {
this.users.push(
typeof user === 'number'
? User.cache[user]
: new User(user)
);
};
function User(user) {
this.id = user.id;
this.username = user.username;
this.password = user.password;
this.groups = [];
User.cache[this.id] = this;
user.groups.forEach(this.addGroup, this);
}
User.cache = {};
User.prototype.addGroup = function(group) {
this.groups.push(
typeof group === 'number'
? Group.cache[group]
: new Group(group)
);
};
// begins the recursion
JSON.parse(
'[{"id":1,"title":"adminGroup","users":[{"id":1,"username":"admin","password":"...","groups":[1]},{"id":31,"username":"user78","password":"...","groups":[1]},{"id":3,"username":"ali","password":"...","groups":[{"id":2,"title":"newsWriterGroup","users":[{"id":14,"username":"staff1","password":"...","groups":[{"id":1005,"title":"FileManagerAccessGroup","users":[{"id":25,"username":"test1","password":"...","groups":[1005]},14]},2]},3]},1]}]}]'
).forEach(function(group) { new Group(group) });
function stopCircularWithId(key, value) {
return key === 'users' || key === 'groups'
? value.map(function(u) { return u.id })
: value;
}
console.log('groups:', JSON.stringify(Group.cache, stopCircularWithId, 4));
console.log('users:', JSON.stringify(User.cache, stopCircularWithId, 4));
JSFiddle

Json Array object to string logic

Not sure if I'm repeating the question or concept.
How do I convert the below sample to the below string format (may not be correct JSON format)
[{ "Name":"Test1","check":"true},{ "Name":"Test2","check":"true},{ "Name":"Test3","check":"false"}]
string format with appending - for false
Expected o/p:
"Test1","Test2","-Test3"
I have tried concatenating, but it always ends up with
"Test1,Test2-Test3"
But I am looking for 3 separate string separated by comma. Any hint would help
You can simply iterate through your array and collect the object in your required format:
var obj = [{
"Name" : "Test1",
"check" : true
}, {
"Name" : "Test2",
"check" : true
}, {
"Name" : "Test3",
"check" : false
}
];
var result = obj.map(function(x) {
return x.check ? x.Name : "-" + x.Name;
});
document.body.innerHTML = JSON.stringify(result);
Note that I have changed the format of your JSON in order to make it valid.
Just in case if you actually have a string true and false, and you can't change this, you can simply compare it as a string:
var obj = [{
"Name" : "Test1",
"check" : "true"
}, {
"Name" : "Test2",
"check" : "true"
}, {
"Name" : "Test3",
"check" : "false"
}
];
var result = obj.map(function(x) {
return x.check === 'true' ? x.Name : "-" + x.Name;
});
document.body.innerHTML = JSON.stringify(result);
HTML
<div id="output"></div>
Javascript
var obj = [{
"Name" : "Test1",
"check" : true
}, {
"Name" : "Test2",
"check" : true
}, {
"Name" : "Test3",
"check" : false
}
];
function getNames(){
var length=obj.length;
// alert(length);
var op=[];
for(var i=0;i<obj.length;i++){
// alert(obj[i].Name);
op[i]='"'+obj[i].Name+'"';
}
document.getElementById("output").innerHTML=op;
}
getNames();
Your output is there as expected.
Just loop through the valid JSON array(obj) and append the required values(obj.Name) to the empty string(str) based on the condition(appending '-' for 'false' value of obj.check).
var obj = [{
"Name" : "Test1",
"check" : true
}, {
"Name" : "Test2",
"check" : true
}, {
"Name" : "Test3",
"check" : false
}
];
var str = '';
for(var x in obj){
str += (obj[x].check === true) ? obj[x].Name : '-'+obj[x].Name;
str += (x != (obj.length-1)) ? ',' : '';
}
alert(str);

On using php mongo execute command showing an error "exception: can't have . in field names", and error code : 16722

I am trying to run a set of java script and update command using by php mongo execute command:
$pSsId = '123456789';
$pUid = 14;
$pRowID = '6fce077519d838bb8ed401448dae6e3a';
$pKey = 'name';
$pValue = 'King Kobra';
$response = $db()->execute("
function(pSsid, pUid, pRowid, pKey, pValue){
udocs = db.VizSpreadsheet.findOne({'_id' : pSsid, 'data.uid' : pUid }).data;
posU = udocs.map(function(d) { return d.uid; }).indexOf(pUid);
posR = udocs[posU].rows.map(function(r) { return r.row_id; }).indexOf(pRowid);
var setCriteria = {};
setCriteria['_id'] = pSsid;
setCriteria['data.uid'] = pUid;
var setObject = {};
setObject['data.'+posU+'.'+'rows'+'.'+posR+'.'+pKey] = pValue;
db.VizSpreadsheet.update(
{
setCriteria
},
{
'$set': setObject
}
);
}", array($pSsId, $pUid, $pRowID, $pKey, $pValue));
But the result is error
Array ( [errmsg] => exception: can't have . in field names [data.1.rows.0.2#12#07337187ee7e48f92ed1689b22d7ed77] at src/mongo/shell/collection.js:155 [code] => 16722 [ok] => 0 )
The collection will look like this
"_id" : "123456789",
"data" : [
{
"uid" : 12,
"rows" : [
{
"row_id" : "8979afefedb42aa8c62e9baa83e35ba0",
"updated_by" : "12",
"updated_at" : "1428644989",
"name" : "AAAAAAAAAAA"
},
{
"row_id" : "7415f767c62a84173d1dcf82ad1d809d",
"updated_by" : "12",
"updated_at" : "1428644989",
"name" : "BBBBBBBBBBBBB"
}
]
},
{
"uid" : 14,
"rows" : [
{
"row_id" : "21b1120811cfe893486e9e9afbebb660",
"updated_by" : "12",
"updated_at" : 1428644989,
"name" : "CCCCCCCCCC"
},
{
"row_id" : "6fce077519d838bb8ed401448dae6e3a",
"updated_by" : "12",
"updated_at" : 1428644841,
"names" : "DDDDDDDDDDD"
}
]
}
What i am trying is to update "name" field of second element in "rows" array for "uid" = 14. The data is updated by '$set' method and specifying the element position which is find by javascript code.
The same code executed successfully in shell.
But in php it fails to detect the position operator.
As an error message says, you cannot use . (dots) within your data.
Try separate your 'subfields' with : for example:
setObject['data:'+posU+':'+'rows'+':'+posR+':'+pKey] = pValue;

Categories

Resources