In Nodejs with querystring how to encode array with single item - node.js

I have an object like this:
const querystring = require('querystring');
let data = {
name: 'Bill',
hobbies: ['Painting', 'Running']
}
If I encode the object like this:
console.log(querystring.encode(data));
I get this:
name=Bill&hobbies=Painting&hobbies=Running
Then when I decode it:
console.log(querystring.decode(querystring.encode(data));
It comes back perfectly like this:
{
name: 'Bill',
hobbies: ['Painting', 'Running']
}
However if I pass an object with array data that has only one item in it like this:
let data = {
name: 'Bill',
hobbies: ['Painting']
}
When I encode / decode it:
console.log(querystring.decode(querystring.encode(data));
This comes back:
{
name: 'Bill',
hobbies: 'Painting'
}
Notice how it converts the array to a single string, rather than an array with a single item.
Is there anyway around this limitation with querystring? Or is there another module that handles this better? I've been looking around and can't find anything.

Related

Storing and querying JSON arrays in Redisjson with nodejs

What I was hoping to do was store an array of objects using RedisJSON very simply and then query that array.
I have something similar to this:
const data = [
{
_id: '63e7d1d85ad7e2f69df8ed6e',
artist: {
genre: 'rock',
},
},
{
_id: '63e7d1d85ad7e2f69df8ed6f',
artist: {
genre: 'metal',
},
},
{
_id: '63e7d1d85ad7e2f69df8ed6g',
artist: {
genre: 'rock',
},
},
]
then I can easily store and retrieve this:
await redisClient.json.set(cacheKey, '$', data)
await redisClient.json.get(cacheKey)
works great. but now I want to also query this data, I've tried creating an index as below:
await redisClient.ft.create(
`idx:gigs`,
{
'$.[0].artist.genre': {
type: SchemaFieldTypes.TEXT,
AS: 'genre',
},
},
{
ON: 'JSON',
PREFIX: 'GIGS',
}
)
and when I try and search this index what I expect is it to return the 2 documents with the correct search filter, but instead it always returns the entire array:
const searchResult = await redisClient.ft.search(`idx:gigs`, '#genre:(rock)')
produces:
{
total: 1,
documents: [
{ id: 'cacheKey', value: [Array] }
]
}
I can't quite work out at which level I'm getting this wrong, but any help would be greatly appreciated.
Is it possible to store an array of objects and then search the nested objects for nested values with RedisJSON?
The Search capability in Redis stack treats each key containing a JSON document as a separate search index entry. I think what you are doing is perhaps storing your whole array of documents in a single Redis key, which means any matches will return the document at that key which contains all of your data.
I would suggest that you store each object in your data array as its own key in Redis. Make sure that these will be indexed by using the GIGS prefix in the key name, for example GIGS:63e7d1d85ad7e2f69df8ed6e and GIGS:63e7d1d85ad7e2f69df8ed6f.
You'd want to change your index definition to account for each document being an object too so it would look something like this:
await redisClient.ft.create(
`idx:gigs`,
{
'$.artist.genre': {
type: SchemaFieldTypes.TEXT,
AS: 'genre',
},
},
{
ON: 'JSON',
PREFIX: 'GIGS:',
}
)
Note I also updated your PREFIX to be GIGS: not GIGS - this isn't strictly necessary, but does stop your index from accidentally looking at other keys in Redis whose name begins GIGS<whatever other characters>.

get RealmResults in array instead of object in NodeJs

I have a simple Schema
const MediaElementSchema = {
primaryKey: 'id',
name: 'MediaElement',
properties: {
id: 'int',
type: 'string',
path: 'string'
}
}
When I try to get all:
let elements = realm.objects('MediaElement')
Realm returns the results in an object like below:
{"0": Record1, "1" : Record2, etc}
is there a way for realm to return an array of the elements like:
[Element1, Element2, etc]
I checked the documentation but didn't find anything relevant about the return type.
https://realm.io/docs/javascript/latest
You could just use plain old javascript to convert object into array.
let elements = {'0': 'Record1', '1' : 'Record2'};
elements = Object.keys(elements).map(key => elements[key]);
console.log(elements); // ["Record1", "Record2"]

Access a specific property in Object.keys adonis.js (Node.js)

I have a query that returns an array, with Object.key (array) .foreach I am iterating, I want to know the value of a property in specific array.
Example:
Object.keys(arreglo).forEach(function(key) {
console.log(arreglo[key]);
});
The output is:
name: "Pepito",
Surname: "Perez"
I want to know how to get only the value of the surname
I know it will not work but it would be something like:
console.log(arreglo[key].surname);
You can use Array.forEach on the original array as shown below. You can even extract the fields you are interested using Array.map.
// let's assume the arrary you got from your query is in this format
const arreglo = [
{ firstname: "fn1", surname: "ln1"},
{ firstname: "fn2", surname: "ln2"},
{ firstname: "fn3", surname: "ln3"}
];
// you can log `surname` for each entry in the array
arreglo.forEach(v => console.log(v.surname));
// you can use map to transform the array to just have `surname` using array.map()
const surnames = arreglo.map(v => v.surname);
console.log(surnames);
Is this what you are looking for
const object1 = {
a: {firstname:"sali",lastname:"mali"},
b: {firstname:"sali",lastname:"mali"},
c: {firstname:"sali",lastname:"mali"}
};
Object.keys(object1).forEach(function(key){console.log(object1[key].lastname)});

how to get json rest response - node.js

How can i get JSON objects in the following case:
Here is my post request:
var articles = client.post("http://host:port/path", args, function (data, response) {
// console.log(xml.parseBuffer(data))
console.log(data.toString('utf8'));
// return xml.parseBuffer(data);
});
result of data.toString('utf8') look like:
<WebServiceResponse>
<page>
...
</page>
<articleDataList>
<articleId>
<idArticle>100000</idArticle>
<index>test</index>
</articleId>
<goodType>test</goodType>
<idAttributeSubject>100001</idAttributeSubject>
<identyfiable>false</identyfiable>
<isActive>true</isActive>
<isGoodSet>false</isGoodSet>
<longName>test</longName>
<translationSubjectId>
<idTranslationSubject>100408</idTranslationSubject>
</translationSubjectId>
<unitCode>szt</unitCode>
<vatRate>0.2300</vatRate>
</articleDataList>
<articleDataList>
...
</articleDataList>
<articleDataList>
...
and xml.parseBuffer(data) looks:
{ name: 'articleDataList', childs: [Object] },
I need put into articles objects with only: idArticle, index and shortName
Is there any easy way?
In this output:
{ name: 'articleDataList', childs: [Object] }
Object represents javascript object that you need to stringify like this: JSON.stringify(Object)
Or you should convert this whole Buffer to string first, and then convert to JSON or javascript object:
xml.parseString(data.toString('utf8'))

Replacing an object in an object array in Redux Store using Javascript/Lodash

I have an object array in a reducer that looks like this:
[
{id:1, name:Mark, email:mark#email.com},
{id:2, name:Paul, email:paul#gmail.com},
{id:3,name:sally, email:sally#email.com}
]
Below is my reducer. So far, I can add a new object to the currentPeople reducer via the following:
const INITIAL_STATE = { currentPeople:[]};
export default function(state = INITIAL_STATE, action) {
switch (action.type) {
case ADD_PERSON:
return {...state, currentPeople: [ ...state.currentPeople, action.payload]};
}
return state;
}
But here is where I'm stuck. Can I UPDATE a person via the reducer using lodash?
If I sent an action payload that looked like this:
{id:1, name:Eric, email:Eric#email.com}
Would I be able to replace the object with the id of 1 with the new fields?
Yes you can absolutely update an object in an array like you want to. And you don't need to change your data structure if you don't want to. You could add a case like this to your reducer:
case UPDATE_PERSON:
return {
...state,
currentPeople: state.currentPeople.map(person => {
if (person.id === action.payload.id) {
return action.payload;
}
return person;
}),
};
This can be be shortened as well, using implicit returns and a ternary:
case UPDATE_PERSON:
return {
...state,
currentPeople: state.currentPeople.map(person => (person.id === action.payload.id) ? action.payload : person),
};
Mihir's idea about mapping your data to an object with normalizr is certainly a possibility and technically it'd be faster to update the user with the reference instead of doing the loop (after initial mapping was done). But if you want to keep your data structure, this approach will work.
Also, mapping like this is just one of many ways to update the object, and requires browser support for Array.prototype.map(). You could use lodash indexOf() to find the index of the user you want (this is nice because it breaks the loop when it succeeds instead of just continuing as the .map would do), once you have the index you could overwrite the object directly using it's index. Make sure you don't mutate the redux state though, you'll need to be working on a clone if you want to assign like this: clonedArray[foundIndex] = action.payload;.
This is a good candidate for data normalization. You can effectively replace your data with the new one, if you normalize the data before storing it in your state tree.
This example is straight from Normalizr.
[{
id: 1,
title: 'Some Article',
author: {
id: 1,
name: 'Dan'
}
}, {
id: 2,
title: 'Other Article',
author: {
id: 1,
name: 'Dan'
}
}]
Can be normalized this way-
{
result: [1, 2],
entities: {
articles: {
1: {
id: 1,
title: 'Some Article',
author: 1
},
2: {
id: 2,
title: 'Other Article',
author: 1
}
},
users: {
1: {
id: 1,
name: 'Dan'
}
}
}
}
What's the advantage of normalization?
You get to extract the exact part of your state tree that you want.
For instance- You have an array of objects containing information about the articles. If you want to select a particular object from that array, you'll have to iterate through entire array. Worst case is that the desired object is not present in the array. To overcome this, we normalize the data.
To normalize the data, store the unique identifiers of each object in a separate array. Let's call that array as results.
result: [1, 2, 3 ..]
And transform the array of objects into an object with keys as the id(See the second snippet). Call that object as entities.
Ultimately, to access the object with id 1, simply do this- entities.articles["1"].
If you want to replace the old data with new data, you can do this-
entities.articles["1"] = newObj;
Use native splice method of array:
/*Find item index using lodash*/
var index = _.indexOf(currentPeople, _.find(currentPeople, {id: 1}));
/*Replace item at index using splice*/
arr.splice(index, 1, {id:1, name:'Mark', email:'mark#email.com'});

Resources