This may be a non-issue however I can't help but feel like there is a better way to do what I am trying to achieve.
I am writing an API in Express with my data stored in a neo4j database.
I am using the official neo4j-driver to interface with neo4j which is running locally. When I run a query eg :
session
.run(`MATCH (foo:FamilyMember)-[:HAS_SISTER]->(sister:FamilyMember)
WHERE foo.firstName = 'bar'
RETURN sister.firstName AS Name, sister.lastName AS Surname
`)
.then(res => {
console.log(res);
})
Neo4j returns a response object with a lot of information about the request:
{
records: [
Record {
keys: [Array],
length: 2,
_fields: [Array],
_fieldLookup: [Object]
},
Record {
keys: [Array],
length: 2,
_fields: [Array],
_fieldLookup: [Object]
},
Record {
keys: [Array],
length: 2,
_fields: [Array],
_fieldLookup: [Object]
},
Record {
keys: [Array],
length: 2,
_fields: [Array],
_fieldLookup: [Object]
}
],
summary: ResultSummary {
query: {
text: 'MATCH (foo:FamilyMember)-[:HAS_SISTER]->(sister:FamilyMember)\n' +
" WHERE foo.firstName = 'bar'\n" +
' RETURN sister.firstName AS Name, sister.lastName AS Surname\n' +
' ',
parameters: {}
},
queryType: 'r',
counters: QueryStatistics { _stats: [Object], _systemUpdates: 0 },
updateStatistics: QueryStatistics { _stats: [Object], _systemUpdates: 0 },
plan: false,
profile: false,
notifications: [],
server: ServerInfo {
address: 'localhost:7687',
version: 'Neo4j/4.2.1',
protocolVersion: 4.2
},
resultConsumedAfter: Integer { low: 0, high: 0 },
resultAvailableAfter: Integer { low: 4, high: 0 },
database: { name: 'neo4j' }
}
}
This is a pain when really I what I want is either the actual response data as an array of objects or an error message if something fails.
I wrote this parse method to generate an array of Javascript object's with the data returned from the query:
function parseNeo4jResponseJSON(res) {
return results = res.records.reduce( (array, currentRecord) => {
const record = currentRecord.keys.reduce( (obj, key, index) => {
obj[key] = currentRecord._fields[index]
return obj
}, {})
array.push(record);
return array;
},[])
};
This works and now when I console log the query response through my parser I get it in the format I want eg:
[
{ Name: 'foo', Surname: 'bar' },
{ Name: 'foo2', Surname: 'bar2' },
...
]
Is this approach going to cause me problems down the line? Is there a better way to get a javascript object from the response? I am pretty new to neo4j. Apologies if the answer is obvious.
Based on the existing examples, what about:
session
.readTransaction((tx) =>
tx.run(`MATCH (foo:FamilyMember)-[:HAS_SISTER]->(sister:FamilyMember)
WHERE foo.firstName = 'bar'
RETURN sister.firstName AS Name, sister.lastName AS Surname`)
)
.then(results => results.records.map((record) => {
return {
Name: record.get('Name'),
Surname: record.get('Surname')
}
})
You could keep session.run, but the session.{read,write}Transaction variants are usually recommended because they work in every environment (where session.run may sometimes fail in a cluster environment).
Please also make sure to use a dictionary of parameters (2nd argument of tx.run) instead of using string interpolation, if your query needs to be parameterized. If the value of foo.firstName comes from a variable (let's say someFirstName), the tx.run would become:
tx.run("MATCH (foo:FamilyMember)-[:HAS_SISTER]->(sister:FamilyMember)
WHERE foo.firstName = $firstName
RETURN sister.firstName AS Name, sister.lastName AS Surname",
{firstName: someFirstName})
Related
If I make a request to a Postgres database with Sequelize, I get the next result:
[
Tags {
dataValues: { idtag: 18 },
_previousDataValues: { idtag: 18 },
_changed: {},
_modelOptions: {
...
},
_options: {
...
},
isNewRecord: false
},
Tags {
dataValues: { idtag: 19 },
_previousDataValues: { idtag: 19 },
_changed: {},
_modelOptions: {
...
},
_options: {
...
},
isNewRecord: false
},
Tags {
dataValues: { idtag: 20 },
_previousDataValues: { idtag: 20 },
_changed: {},
_modelOptions: {
...
},
_options: {
...
},
isNewRecord: false
}
]
I can't find the way to loop this to can get the 'idtag' values.
I tried to parse this to JSON with JSON.stringify() but it gives me a string. Also, I tried to loop this like it was an array but it didn't works too.
Let's assume that your output is stored to an array. Now using following piece of code you can collect idTag values.
const idTagVals = [];
array.forEach(element => {
idTagVals.push(element.dataValues.idtag);
});
console.log(idTagVals); //[ 18, 19, 20 ]
According to sequelize docs
TagsModel.findAll({where: {} ,plain:true});
Will return Array of plain objects.
And finilly I have the answer. First I converted the result with JSON.stringify() and then with JSON.parse().
let tags = await models.Tags.findAll({ attributes: ['idtag'], where: { iduser: iduser } });
let string = JSON.stringify(tags);
tags = JSON.parse(string);
And finally, to loop:
tags.forEach(async (tag) => {
...
});
I have an api endpoint form where I am getting data like below. How i will access the values title, short_title etc.
blog: {
paginations: true,
isLoading: false,
particularBlog: [],
count: 13,
next: 'http://127.0.0.1:8000/api/blog/all-blog/?page=2',
previous: null,
results: [
{
id: 47,
user: 1,
title: 'adasd',
short_title: 'asd',
publish: '2019-09-16',
slug: 'adasd',
comments_count: 0,
likes_count: 0
},
{
id: 46,
user: 1,
title: 'adasda',
short_title: 'asdas',
publish: '2019-09-16',
slug: 'adasda',
comments_count: 0,
likes_count: 0
}
]
},
what i have done is
<div>{
this.props.blog && Object.keys(this.props.blog).map((key) => {
return <p>{this.props.blog.results[key]}</p>
})
}</div>
but it is giving error stating paginations' of undefined. Can someone please pointout what i am doing wrong here?
Where is what is happening
Object.keys(this.props.blog).map((key) => { is getting the keys of this.props.blog and this.props.blog.results[key] is trying to access the properties of results with the keys of blog.
What you should do is have another .map with Object.keys of this.props.blog.results
OR
What I think you are trying to do is list all properties on the this.props.blog.results array, so here is what you can do
this.props.blog && this.props.blog.results && this.props.blog.results.map(result=> <p>{result.short_title}</p>
You do .map on the results array and display short_title.
blog.results.map(el => (<div>{el.short_title}</div>))
I need to populate array of ids with objects. In other words I have. Array of ids:
var orderArray = ["5ace454a2b22e17597d0e694", "5acde7c0f7d2520e3b205971", "5ad2086bf05ad342dc723ea1"]
And array of objects:
var objectsArray = [ { _id: 5acde7c0f7d2520e3b205971,
name: 'Dinner',
restaurant: 5a68d8ea17d9e4308e6400c3,
created: 2018-04-11T10:47:28.957Z,
status: true,
products: [ [Object] ] },
{ _id: 5ace454a2b22e17597d0e694,
name: 'Test',
restaurant: 5a68d8ea17d9e4308e6400c3,
image:
{ _id: 5ad23ed177bcd07303f62899,
filename: 'rJKCR2k2f-1523728081111.jpeg',
destination: 'images',
binded: true },
created: 2018-04-11T17:26:34.186Z,
status: false,
products: [ [Object], [Object] ] },
{ _id: 5ad2086bf05ad342dc723ea1,
name: 'Test',
restaurant: 5a68d8ea17d9e4308e6400c3,
image: null,
created: 2018-04-14T13:55:55.449Z,
status: true,
products: [] } ]
Either you can sort array of objects based on ids... Or map array of ids to array of objects. Probably I'd prefer the second option.
But my approach just doesn't work
orderArray.map(id => objectsArray.filter(obj => obj._id == id))
The result shall be: objectsArray is sorted as order of elements in orderArray
SOLUTION: I've opened this question few days ago: Merging 2 arrays with different value types
Here I have the same problem. orderArray is array of objects (not string) thus in order to make it work I need to apply the solution I found earlier (both Array.filter and Array.find functions works well):
but in my way it will work only if:
order_array.map(String).map(e => objectsArray.find(a => a._id == e))
//as well as
order_array.map(String).map(e => objectsArray.filter(a => a._id == e))
map the first array to fill it with corresponding elements from the second one :
var orderArray = ["5ace454a2b22e17597d0e694", "5acde7c0f7d2520e3b205971", "5ad2086bf05ad342dc723ea1"]
var objectsArray = [ { _id: '5acde7c0f7d2520e3b205971',
name: 'Dinner',
restaurant: '5a68d8ea17d9e4308e6400c3',
created: '2018-04-11T10:47:28.957Z',
status: true,
products: [ [Object] ] },
{ _id: '5ace454a2b22e17597d0e694',
name: 'Test',
restaurant: '5a68d8ea17d9e4308e6400c3',
image:
{ _id: '5ad23ed177bcd07303f62899',
filename: 'rJKCR2k2f-1523728081111.jpeg',
destination: 'images',
binded: true },
created: '2018-04-11T17:26:34.186Z',
status: false,
products: [ [Object], [Object] ] },
{ _id: '5ad2086bf05ad342dc723ea1',
name: 'Test',
restaurant: '5a68d8ea17d9e4308e6400c3',
image: null,
created: '2018-04-14T13:55:55.449Z',
status: true,
products: [] } ]
var sorted = orderArray.map((e) => { return objectsArray.find((a) => { return a._id == e})})
console.log(sorted)
You should be able to:
objectsArray.filter(obj => ordersArray.includes(obj._id));
If I am understanding correctly.
Using map/find (instead of filter):
let mappedArray = orderArray.map(id => objectsArray.find(obj => obj._id == id));
which maps orderArray to an array of objects, where it finds the object from objectsArray that has the same _id as the current id.
Note: If there is no object in objectsArray that matches the id, null will be returned.
I'm writing a Firebase Cloud Function and I'm trying to figure out how Promise.all works. In my code, I pass in an array of database queries and I'm trying the read the resulting array, but I'm only getting garbage:
T {
A:
P {
k: Sb { Ka: [Function: vb], ba: [Object] },
aa: P { k: [Object], aa: null, wb: [Object], Bb: '' },
wb: Zc { ld: [Object], ac: [Object] },
Bb: null },
V:
R {
u:
Gd {
app: [Object],
L: [Object],
Ua: [Object],
Sc: null,
ca: [Object],
td: 1,
Qa: [Object],
va: [Object],
qg: [Object],
jc: [Object],
ee: [Object],
md: [Object],
ia: [Object],
Xa: [Object],
cd: 2,
fe: null,
K: [Object] },
path: J { o: [Object], Y: 0 },
m:
Df {
xa: false,
ka: false,
Ib: false,
na: false,
Pb: false,
oa: 0,
kb: '',
bc: null,
xb: '',
Zb: null,
vb: '',
g: Tc {} },
Kc: false,
then: undefined,
catch: undefined },
g: Tc {} }
I'm expecting a simple json:
{
"name": "Foo",
"number": 2521
// And a few other fields
}
BTW, I watched Jen's video so I know what I'm doing is wrong anyway; I just want to know why my existing code doesn't work. (I haven't tested it, but I believe the solution is to return the raw snapshots in my db query and then do the .val() call.)
Relevant code if the links disappear:
function mergeTeams(duplicates) {
return Promise.all([
admin.database().ref(someRef).once('value', (snap) => {
return snap.val();
}),
admin.database().ref(someRef2).once('value', (snap) => {
return snap.val();
})
]).then(values => {
console.log(values);
const team1 = values[0];
const team2 = values[1];
console.log(team1);
console.log(team2);
}
So, here's the code that works (and the explanation below):
return Promise.all([
admin.database().ref(teamRef + duplicates.teamKey1).once('value'),
admin.database().ref(teamRef + duplicates.teamKey2).once('value')
]).then(values => {
const team1 = values[0].val();
const team2 = values[1].val();
console.log(team1);
console.log(team2);
});
The reason it works is because I've always getting the promises in the values array even though I didn't know it. Here's what Promise.all returns: an array with the raw result of the promises passed in. When I was returning stuff inside the success callback, that didn't actually do anything because it wasn't part of the promise; I was just returning random stuff to an empty void. And when I was printing the teams, I was actually logging the Firebase Snapshot object instead of the .val().
When my Angular2 component makes a request to get my fake model data object it gets returned like so:
_body: "[↵ {↵ "id": 0,↵ "title": "2017 Oscars",↵ "graphic": "https://wikitags.com/images/OscarsBanner.png",↵
What I am expecting is an Array like so:
[
{ id: 0,
title: '2017 Oscars',
graphic: '/images/OscarsBanner.png',
categorycards: [ [Object], [Object], [Object], [Object] ] },
{ id: 1,
title: '2017 Super Bowl',
graphic: '/images/SuperBowlBanner.png',
categorycards: [ [Object], [Object], [Object], [Object] ] },
{ id: 2,
title: 'What people are talking about',
graphic: null,
categorycards: [ [Object], [Object], [Object], [Object] ] }
]
The Model
What my backend/models/home.ts looks like
export function homeData() {
return [
{
id: 0,
title: '2017 Oscars',
graphic: '/images/OscarsBanner.png',
categorycards: [
{
type: 'image',
graphic: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Ryan_Gosling_2_Cannes_2011_%28cropped%29.jpg/1024px-Ryan_Gosling_2_Cannes_2011_%28cropped%29.jpg?width=440',
title: '2017 Oscar Nominee for Best Actor',
listings: ['Rayn Gosling', 'Denzel Washington', 'Andrew Garfield', 'Casey Affleck', 'Viggo Mortensen']
}
//...
]
}
//...
];
}
The client API
api.service.ts
#Injectable()
export class ApiService {
private getFeaturedUrl: string = '/wiki/api';
constructor(public http: Http) {}
/**
* Get featured categories data for homepage
*/
getFeatured(): Observable<{}> {
return this.http.get(`${this.getFeaturedUrl}/home`)
.do(res => console.log('getFeatured res', res))
.map(res => res.json().data)
.catch(this.handleError);
}
The console.log here:
The homepage component
universalInit() {
console.log('universalInit...')
this.api.getFeatured()
.subscribe(categories => {
console.log('categories', categories);
// this.testFeaturedCategories = categories
});
The Node/Express API endpoint
// API CRUD ////////////////////////////////////////////////////////////////////
app.get('/wiki/api/home', (req, res) => {
console.log('homeData()', homeData());
if (!homeData()) returnError(res, 'No home data found');
res.json(homeData());
});
In the terminal, I see my home.ts model Array:
Any ideas why my res.body is looking jacked up?
It looks like it may be trying to convert the json object twice. Not completely sure though
instead of res.json(homeData())
Try:
res.send(homedata())
If that doesn't work, then my guess would be to go on the angular side and change
.map(JSON.parse(res.json().data))