I have two gremlin traversal queries pretty much doing the same thing, each looks up a vertex with ID and upserts a new node with an edge to the new node.
I tried with this first because this looked cleaner:
g.V('22b515e0-dbefb359-10f3-71ff13527bb2').sideEffect(__.outE().drop())\
.addE('someedge').to(__.V().hasLabel('SomeLabel').has('name', \
'SomeName').sideEffect(__.properties().drop()).property('name123', \
'SomeName123')).next()
This query takes around 8 seconds every time it executes.
As a measure to fix the above issue, I tried changing the traversal to this and the response time is in milliseconds:
g.V().hasLabel('SomeLabel').has('name', \
'SomeName').sideEffect(__.properties().drop()).property('name123', \
'SomeName123').as_('X').V('22b515e0-dbef-b359-10f3-71ff13527bb2')\
.sideEffect(__.outE().drop()).addE('some \
edge').to(__.select('X')).next()
But, when I lookup using ID directly (In method - 1), even with this the response time is in milliseconds.
g.V('22b515e0-dbef-b359-10f3-71ff13527bb2').sideEffect(__.outE().drop())\
.addE('someedge').to(__.V('8b66cab2-3b1c-41c9-9acb-296dda3c9139')\
.sideEffect(__.properties().drop()).property('name123', \
'SomeName123')).next()
Here are some .profile() metrics which shows execution times.
For 1:
{'dur': 8823.148244,
'metrics': [{'dur': 0.336926,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'NeptuneGraphQueryStep(Vertex)',
'annotations': {'percentDur': 0.003818659628994895},
'id': '6.0.0()'},
{'dur': 1.882282,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'TraversalSideEffectStep([VertexStep(OUT,edge), ProfileStep, DropStep, ProfileStep])',
'annotations': {'percentDur': 0.02133345091736396},
'id': '1.0.0()',
'metrics': [{'dur': 0.275912,
'counts': {'traverserCount': 11, 'elementCount': 11},
'name': 'VertexStep(OUT,edge)',
'id': '0.1.0(1.0.0())'},
{'dur': 1.569401,
'counts': {},
'name': 'DropStep',
'id': '1.1.0(1.0.0())'}]},
{'dur': 0.115423,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'NoOpBarrierStep',
'annotations': {'percentDur': 0.0013081838455847213},
'id': '5.0.0()'},
{'dur': 8820.813613,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'AddEdgeStep({~to=[[GraphStep(vertex,[]), ProfileStep, NeptuneHasStep([~label.eq(SomeLabel), name.eq(SomeName)]), ProfileStep, TraversalSideEffectStep([PropertiesStep(property), ProfileStep, DropStep, ProfileStep]), ProfileStep, NoOpBarrierStep, ProfileStep, AddPropertyStep({value=[SomeName123], key=[name123]}), ProfileStep]], label=[some edge]})',
'annotations': {'percentDur': 99.97353970560806},
'id': '2.0.0()',
'metrics': [{'dur': 1346.058324,
'counts': {'traverserCount': 373732, 'elementCount': 373732},
'name': 'GraphStep(vertex,[])',
'id': '0.1.0(2.0.0())'},
{'dur': 7473.661772,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'NeptuneHasStep([~label.eq(SomeLabel), name.eq(SomeName)])',
'id': '5.1.0(2.0.0())'},
{'dur': 0.283139,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'TraversalSideEffectStep([PropertiesStep(property), ProfileStep, DropStep, ProfileStep])',
'id': '2.1.0(2.0.0())',
'metrics': [{'dur': 0.096149,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'PropertiesStep(property)',
'id': '0.2.0(2.1.0(2.0.0()))'},
{'dur': 0.149241,
'counts': {},
'name': 'DropStep',
'id': '1.2.0(2.1.0(2.0.0()))'}]},
{'dur': 0.046801,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'NoOpBarrierStep',
'id': '4.1.0(2.0.0())'},
{'dur': 0.306436,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'AddPropertyStep({value=[SomeName123], key=[name123]})',
'id': '3.1.0(2.0.0())'}]}]}
For 2:
{'dur': 5.596631,
'metrics': [{'dur': 0.510122,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'NeptuneGraphQueryStep(Vertex)',
'annotations': {'percentDur': 9.114804960341319},
'id': '11.0.0()'},
{'dur': 0.462721,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'TraversalSideEffectStep([PropertiesStep(property), ProfileStep, DropStep, ProfileStep])',
'annotations': {'percentDur': 8.267848997012667},
'id': '2.0.0()',
'metrics': [{'dur': 0.179074,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'PropertiesStep(property)',
'id': '0.1.0(2.0.0())'},
{'dur': 0.210574,
'counts': {},
'name': 'DropStep',
'id': '1.1.0(2.0.0())'}]},
{'dur': 0.092257,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'NoOpBarrierStep',
'annotations': {'percentDur': 1.6484381407314508},
'id': '9.0.0()'},
{'dur': 1.653211,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'AddPropertyStep({value=[SomeName123], key=[name123]})#[X]',
'annotations': {'percentDur': 29.539396111696483},
'id': '3.0.0()'},
{'dur': 0.116915,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'GraphStep(vertex,[22b515e0-dbef-b359-10f3-71ff13527bb2])',
'annotations': {'percentDur': 2.0890246292814374},
'id': '4.0.0()'},
{'dur': 1.073502,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'TraversalSideEffectStep([VertexStep(OUT,edge), ProfileStep, DropStep, ProfileStep])',
'annotations': {'percentDur': 19.181218129263836},
'id': '5.0.0()',
'metrics': [{'dur': 0.14199,
'counts': {'traverserCount': 11, 'elementCount': 11},
'name': 'VertexStep(OUT,edge)',
'id': '0.1.0(5.0.0())'},
{'dur': 0.879906,
'counts': {},
'name': 'DropStep',
'id': '1.1.0(5.0.0())'}]},
{'dur': 0.042369,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'NoOpBarrierStep',
'annotations': {'percentDur': 0.7570447292308533},
'id': '10.0.0()'},
{'dur': 1.645534,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'AddEdgeStep({~to=[[SelectOneStep(last,X), ProfileStep]], label=[some edge]})',
'annotations': {'percentDur': 29.40222430244195},
'id': '6.0.0()',
'metrics': [{'dur': 0.024292,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'SelectOneStep(last,X)',
'id': '0.1.0(6.0.0())'}]}]}
For 3:
{'dur': 9.084957,
'metrics': [{'dur': 0.340621,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'NeptuneGraphQueryStep(Vertex)',
'annotations': {'percentDur': 3.7492857698721083},
'id': '6.0.0()'},
{'dur': 1.92865,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'TraversalSideEffectStep([VertexStep(OUT,edge), ProfileStep, DropStep, ProfileStep])',
'annotations': {'percentDur': 21.229049295445208},
'id': '1.0.0()',
'metrics': [{'dur': 0.282423,
'counts': {'traverserCount': 11, 'elementCount': 11},
'name': 'VertexStep(OUT,edge)',
'id': '0.1.0(1.0.0())'},
{'dur': 1.578817,
'counts': {},
'name': 'DropStep',
'id': '1.1.0(1.0.0())'}]},
{'dur': 0.058816,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'NoOpBarrierStep',
'annotations': {'percentDur': 0.647399872118272},
'id': '5.0.0()'},
{'dur': 6.75687,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'AddEdgeStep({~to=[[GraphStep(vertex,[8b66cab2-3b1c-41c9-9acb-296dda3c9139]), ProfileStep, TraversalSideEffectStep([PropertiesStep(property), ProfileStep, DropStep, ProfileStep]), ProfileStep, NoOpBarrierStep, ProfileStep, AddPropertyStep({value=[SomeName123], key=[name123]}), ProfileStep]], label=[some edge]})',
'annotations': {'percentDur': 74.37426506256442},
'id': '2.0.0()',
'metrics': [{'dur': 0.087179,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'GraphStep(vertex,[8b66cab2-3b1c-41c9-9acb-296dda3c9139])',
'id': '0.1.0(2.0.0())'},
{'dur': 0.332149,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'TraversalSideEffectStep([PropertiesStep(property), ProfileStep, DropStep, ProfileStep])',
'id': '1.1.0(2.0.0())',
'metrics': [{'dur': 0.144028,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'PropertiesStep(property)',
'id': '0.2.0(1.1.0(2.0.0()))'},
{'dur': 0.159151,
'counts': {},
'name': 'DropStep',
'id': '1.2.0(1.1.0(2.0.0()))'}]},
{'dur': 0.052224,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'NoOpBarrierStep',
'id': '3.1.0(2.0.0())'},
{'dur': 5.781101,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'AddPropertyStep({value=[SomeName123], key=[name123]})',
'id': '2.1.0(2.0.0())'}]}]}
There are around 300k vertices and 3 million edges in the graph database (AWS Neptune).
Am I missing something here? I wanted to make it work with method-1 as this is a part of a complex traversal which might not work well with method-2
Judging from the profile() of the three queries, Neptune is not optimizing the child traversal of to(V().hasLabel('SomeLabel').has('name','SomeName')). It's doing a full graph scan for V() in that case denoted by this:
{'dur': 8820.813613,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'AddEdgeStep({~to=[[GraphStep(vertex,[]), ProfileStep, NeptuneHasStep([~label.eq(SomeLabel), name.eq(SomeName)]), ProfileStep, TraversalSideEffectStep([PropertiesStep(property), ProfileStep, DropStep, ProfileStep]), ProfileStep, NoOpBarrierStep, ProfileStep, AddPropertyStep({value=[SomeName123], key=
[name123]}), ProfileStep]], label=[some edge]})',
'annotations': {'percentDur': 99.97353970560806},
'id': '2.0.0()',
'metrics': [{'dur': 1346.058324,
'counts': {'traverserCount': 373732, 'elementCount': 373732},
'name': 'GraphStep(vertex,[])',
'id': '0.1.0(2.0.0())'},
{'dur': 7473.661772,
'counts': {'traverserCount': 1, 'elementCount': 1},
'name': 'NeptuneHasStep([~label.eq(SomeLabel), name.eq(SomeName)])',
'id': '5.1.0(2.0.0())'},
See the traverser count for V() is 373732 which feeds into has() which does a 7 second in-memory filter to find 1 vertex.
Related
I have fairly limited experience with React Native. I've set up similar API-calls before without trouble, but for some reason can't get this one to work.
I have the following code which includes state variables and the API fetch function.
export default function App() {
const [users, setUsers] = useState([]);
const [villages, setVillages] = useState([]);
async function getUsers() {
const response = await fetch("https://localhost:7108/PlayersAPI/1");
const users = await response.json();
setUsers(users[0]);
console.log("Before calling setVillages:", users[0].villages[0]); // log the value before calling setVillages
setVillages(users[0].villages[0].villageId);
console.log(villages);
console.log("After calling setVillages:", users[0].villages[0]); // log the value after calling setVillages
}
The function runs from a useEffect:
useEffect(() => {
getUsers();
console.log(villages);
}, []);
The response I get from the API looks like this:
[
{
"playerId": 1,
"username": "Sebastian",
"villages": [
{
"villageId": 1,
"name": "Söderstadion",
"resourceFields": [
{
"resourceFieldId": 1,
"level": 2,
"typeOfResource": 0,
"villageId": 1,
"village": null
},
{
"resourceFieldId": 2,
"level": 1,
"typeOfResource": 1,
"villageId": 1,
"village": null
},
{
"resourceFieldId": 3,
"level": 2,
"typeOfResource": 2,
"villageId": 1,
"village": null
},
{
"resourceFieldId": 4,
"level": 1,
"typeOfResource": 3,
"villageId": 1,
"village": null
}
],
"player": null,
"playerId": 1,
"villageData": {
"villageDataId": 1,
"wood": 7900,
"iron": 7900,
"clay": 7900,
"maxStorage": 8000,
"crop": 20,
"maxCrop": 8000,
"woodProduction": 100,
"ironProduction": 150,
"clayProduction": 100,
"cropProduction": 100,
"resourcesLastUpdated": "2022-12-08T21:52:35.8305912",
"villageId": 1,
"village": null
},
"armies": null,
"tileId": 11,
"tile": {
"tileId": 11,
"worldMapId": 1,
"worldMap": null,
"coordinate": null,
"village": null
}
},
{
"villageId": 2,
"name": "Kennedy",
"resourceFields": [
{
"resourceFieldId": 5,
"level": 1,
"typeOfResource": 0,
"villageId": 2,
"village": null
},
{
"resourceFieldId": 6,
"level": 2,
"typeOfResource": 1,
"villageId": 2,
"village": null
},
{
"resourceFieldId": 7,
"level": 2,
"typeOfResource": 2,
"villageId": 2,
"village": null
},
{
"resourceFieldId": 8,
"level": 1,
"typeOfResource": 3,
"villageId": 2,
"village": null
}
],
"player": null,
"playerId": 1,
"villageData": {
"villageDataId": 2,
"wood": 8000,
"iron": 8000,
"clay": 8000,
"maxStorage": 8000,
"crop": 120,
"maxCrop": 8000,
"woodProduction": 150,
"ironProduction": 150,
"clayProduction": 100,
"cropProduction": 100,
"resourcesLastUpdated": "2022-12-08T21:52:35.8319058",
"villageId": 2,
"village": null
},
"armies": null,
"tileId": 12,
"tile": {
"tileId": 12,
"worldMapId": 1,
"worldMap": null,
"coordinate": null,
"village": null
}
},
{
"villageId": 3,
"name": "Ludwigsson",
"resourceFields": [
{
"resourceFieldId": 9,
"level": 1,
"typeOfResource": 0,
"villageId": 3,
"village": null
},
{
"resourceFieldId": 10,
"level": 2,
"typeOfResource": 1,
"villageId": 3,
"village": null
},
{
"resourceFieldId": 11,
"level": 1,
"typeOfResource": 2,
"villageId": 3,
"village": null
},
{
"resourceFieldId": 12,
"level": 2,
"typeOfResource": 3,
"villageId": 3,
"village": null
}
],
"player": null,
"playerId": 1,
"villageData": {
"villageDataId": 3,
"wood": 8000,
"iron": 8000,
"clay": 8000,
"maxStorage": 8000,
"crop": 120,
"maxCrop": 8000,
"woodProduction": 150,
"ironProduction": 100,
"clayProduction": 100,
"cropProduction": 150,
"resourcesLastUpdated": "2022-12-08T21:52:35.8319149",
"villageId": 3,
"village": null
},
"armies": null,
"tileId": 13,
"tile": {
"tileId": 13,
"worldMapId": 1,
"worldMap": null,
"coordinate": null,
"village": null
}
}
],
"playerData": {
"playerDataId": 1,
"wood": 100,
"iron": 750,
"clay": 350,
"maxStorage": 800,
"crop": 120,
"maxCrop": 800,
"woodProduction": 100,
"ironProduction": 100,
"clayProduction": 100,
"cropProduction": 0,
"resourcesLastUpdated": "2022-12-04T20:00:09.3110368",
"playerId": 1,
"player": null
}
}
]
The users state works as expected, it fetches everything that has to do with the first player (in this case there is only one though). I can then console.log(users[0].villages[0]) and get the exact output I'm interested in, an object looking like this:
{
"villageId": 1,
"name": "Söderstadion",
"resourceFields": [
{
"resourceFieldId": 1,
"level": 2,
"typeOfResource": 0,
"villageId": 1,
"village": null
},
{
"resourceFieldId": 2,
"level": 1,
"typeOfResource": 1,
"villageId": 1,
"village": null
},
{
"resourceFieldId": 3,
"level": 2,
"typeOfResource": 2,
"villageId": 1,
"village": null
},
{
"resourceFieldId": 4,
"level": 1,
"typeOfResource": 3,
"villageId": 1,
"village": null
}
],
"player": null,
"playerId": 1,
"villageData": {
"villageDataId": 1,
"wood": 7900,
"iron": 7900,
"clay": 7900,
"maxStorage": 8000,
"crop": 20,
"maxCrop": 8000,
"woodProduction": 100,
"ironProduction": 150,
"clayProduction": 100,
"cropProduction": 100,
"resourcesLastUpdated": "2022-12-08T21:52:35.8305912",
"villageId": 1,
"village": null
},
"armies": null,
"tileId": 11,
"tile": {
"tileId": 11,
"worldMapId": 1,
"worldMap": null,
"coordinate": null,
"village": null
}
}
But for the life of me I cannot get setVillages(users[0].villages[0].villageId); to work. All it returns is an empty array. I've set up a console.log before and after setVillages is used, and both return the object. But when I console.log(villages) it returns an empty array [].
What is it that I'm missing here?
use it inside a useEffect to detect changes since usestate is asynchronous.
useEffect(() => {
console.log(villages)
}, [villages])
I am trying to display JSON data to a DataTable in Flutter. The data is coming from an API, getting data is no problem. But I am running to a problem displaying the list of some data in DataTable, I think is because of the JSON structure.
Here is the JSON sample
"response": [
{
"league": {
"id": 1,
"name": "World Cup",
"country": "World",
"logo": "https://media.api-sports.io/football/leagues/1.png",
"flag": null,
"season": 2018,
"standings": [
[
{
"rank": 1,
"team": {
"id": 7,
"name": "Uruguay",
"logo": "https://media.api-sports.io/football/teams/7.png"
},
"points": 9,
"goalsDiff": 5,
"group": "FIFA World Cup: Group A",
"form": "WWW",
"status": "same",
"description": "8th Finals",
"all": {
"played": 3,
"win": 3,
"draw": 0,
"lose": 0,
"goals": {
"for": 5,
"against": 0
}
},
"home": {
"played": 2,
"win": 2,
"draw": 0,
"lose": 0,
"goals": {
"for": 4,
"against": 0
}
},
"away": {
"played": 1,
"win": 1,
"draw": 0,
"lose": 0,
"goals": {
"for": 1,
"against": 0
}
},
"update": "2020-06-18T00:00:00+00:00"
},
{
"rank": 2,
"team": {
"id": 4,
"name": "Russia",
"logo": "https://media.api-sports.io/football/teams/4.png"
},
"points": 6,
"goalsDiff": 4,
"group": "FIFA World Cup: Group A",
"form": "LWW",
"status": "same",
"description": "8th Finals",
"all": {
"played": 3,
"win": 2,
"draw": 0,
"lose": 1,
"goals": {
"for": 8,
"against": 4
}
},
"home": {
"played": 2,
"win": 2,
"draw": 0,
"lose": 0,
"goals": {
"for": 8,
"against": 1
}
},
"away": {
"played": 1,
"win": 0,
"draw": 0,
"lose": 1,
"goals": {
"for": 0,
"against": 3
}
},
"update": "2020-06-18T00:00:00+00:00"
},
{
"rank": 3,
"team": {
"id": 23,
"name": "Saudi Arabia",
"logo": "https://media.api-sports.io/football/teams/23.png"
},
"points": 3,
"goalsDiff": -5,
"group": "FIFA World Cup: Group A",
"form": "WLL",
"status": "same",
"description": null,
"all": {
"played": 3,
"win": 1,
"draw": 0,
"lose": 2,
"goals": {
"for": 2,
"against": 7
}
},
"home": {
"played": 1,
"win": 1,
"draw": 0,
"lose": 0,
"goals": {
"for": 2,
"against": 1
}
},
"away": {
"played": 2,
"win": 0,
"draw": 0,
"lose": 2,
"goals": {
"for": 0,
"against": 6
}
},
"update": "2020-06-18T00:00:00+00:00"
},
{
"rank": 4,
"team": {
"id": 32,
"name": "Egypt",
"logo": "https://media.api-sports.io/football/teams/32.png"
},
"points": 0,
"goalsDiff": -4,
"group": "FIFA World Cup: Group A",
"form": "LLL",
"status": "same",
"description": null,
"all": {
"played": 3,
"win": 0,
"draw": 0,
"lose": 3,
"goals": {
"for": 2,
"against": 6
}
},
"home": {
"played": 1,
"win": 0,
"draw": 0,
"lose": 1,
"goals": {
"for": 0,
"against": 1
}
},
"away": {
"played": 2,
"win": 0,
"draw": 0,
"lose": 2,
"goals": {
"for": 2,
"against": 5
}
},
"update": "2020-06-18T00:00:00+00:00"
}
],
[
{
"rank": 1,
"team": {
"id": 9,
"name": "Spain",
"logo": "https://media.api-sports.io/football/teams/9.png"
},
"points": 5,
"goalsDiff": 1,
"group": "FIFA World Cup: Group B",
"form": "WWW",
"status": "same",
"description": "8th Finals",
"all": {
"played": 3,
"win": 1,
"draw": 2,
"lose": 0,
"goals": {
"for": 6,
"against": 5
}
},
"home": {
"played": 1,
"win": 0,
"draw": 1,
"lose": 0,
"goals": {
"for": 2,
"against": 2
}
},
"away": {
"played": 2,
"win": 1,
"draw": 1,
"lose": 0,
"goals": {
"for": 4,
"against": 3
}
},
"update": "2020-06-18T00:00:00+00:00"
},
{
"rank": 2,
"team": {
"id": 27,
"name": "Portugal",
"logo": "https://media.api-sports.io/football/teams/27.png"
},
"points": 5,
"goalsDiff": 1,
"group": "FIFA World Cup: Group B",
"form": "LWW",
"status": "same",
"description": "8th Finals",
"all": {
"played": 3,
"win": 1,
"draw": 2,
"lose": 0,
"goals": {
"for": 5,
"against": 4
}
},
"home": {
"played": 2,
"win": 1,
"draw": 1,
"lose": 0,
"goals": {
"for": 4,
"against": 3
}
},
"away": {
"played": 1,
"win": 0,
"draw": 1,
"lose": 0,
"goals": {
"for": 1,
"against": 1
}
},
"update": "2020-06-18T00:00:00+00:00"
},
{
"rank": 3,
"team": {
"id": 22,
"name": "Iran",
"logo": "https://media.api-sports.io/football/teams/22.png"
},
"points": 4,
"goalsDiff": 0,
"group": "FIFA World Cup: Group B",
"form": "WLL",
"status": "same",
"description": null,
"all": {
"played": 3,
"win": 1,
"draw": 1,
"lose": 1,
"goals": {
"for": 2,
"against": 2
}
},
"home": {
"played": 2,
"win": 0,
"draw": 1,
"lose": 1,
"goals": {
"for": 1,
"against": 2
}
},
"away": {
"played": 1,
"win": 1,
"draw": 0,
"lose": 0,
"goals": {
"for": 1,
"against": 0
}
},
"update": "2020-06-18T00:00:00+00:00"
},
{
"rank": 4,
"team": {
"id": 31,
"name": "Morocco",
"logo": "https://media.api-sports.io/football/teams/31.png"
},
"points": 1,
"goalsDiff": -2,
"group": "FIFA World Cup: Group B",
"form": "LLL",
"status": "same",
"description": null,
"all": {
"played": 3,
"win": 0,
"draw": 1,
"lose": 2,
"goals": {
"for": 2,
"against": 4
}
},
"home": {
"played": 1,
"win": 0,
"draw": 0,
"lose": 1,
"goals": {
"for": 0,
"against": 1
}
},
"away": {
"played": 2,
"win": 0,
"draw": 1,
"lose": 1,
"goals": {
"for": 2,
"against": 3
}
},
"update": "2020-06-18T00:00:00+00:00"
}
],
[
{
"rank": 1,
"team": {
"id": 2,
"name": "France",
"logo": "https://media.api-sports.io/football/teams/2.png"
},
"points": 7,
"goalsDiff": 2,
"group": "FIFA World Cup: Group C",
"form": "WWW",
"status": "same",
"description": "8th Finals",
"all": {
"played": 3,
"win": 2,
"draw": 1,
"lose": 0,
"goals": {
"for": 3,
"against": 1
}
},
"home": {
"played": 2,
"win": 2,
"draw": 0,
"lose": 0,
"goals": {
"for": 3,
"against": 1
}
},
"away": {
"played": 1,
"win": 0,
"draw": 1,
"lose": 0,
"goals": {
"for": 0,
"against": 0
}
},
"update": "2020-06-18T00:00:00+00:00"
},
{
"rank": 2,
"team": {
"id": 21,
"name": "Denmark",
"logo": "https://media.api-sports.io/football/teams/21.png"
},
"points": 5,
"goalsDiff": 1,
"group": "FIFA World Cup: Group C",
"form": "LWW",
"status": "same",
"description": "8th Finals",
"all": {
"played": 3,
"win": 1,
"draw": 2,
"lose": 0,
"goals": {
"for": 2,
"against": 1
}
},
"home": {
"played": 2,
"win": 0,
"draw": 2,
"lose": 0,
"goals": {
"for": 1,
"against": 1
}
},
"away": {
"played": 1,
"win": 1,
"draw": 0,
"lose": 0,
"goals": {
"for": 1,
"against": 0
}
},
"update": "2020-06-18T00:00:00+00:00"
},
{
"rank": 3,
"team": {
"id": 30,
"name": "Peru",
"logo": "https://media.api-sports.io/football/teams/30.png"
},
"points": 3,
"goalsDiff": 0,
"group": "FIFA World Cup: Group C",
"form": "WLL",
"status": "same",
"description": null,
"all": {
"played": 3,
"win": 1,
"draw": 0,
"lose": 2,
"goals": {
"for": 2,
"against": 2
}
},
"home": {
"played": 1,
"win": 0,
"draw": 0,
"lose": 1,
"goals": {
"for": 0,
"against": 1
}
},
"away": {
"played": 2,
"win": 1,
"draw": 0,
"lose": 1,
"goals": {
"for": 2,
"against": 1
}
},
"update": "2020-06-18T00:00:00+00:00"
},
{
"rank": 4,
"team": {
"id": 20,
"name": "Australia",
"logo": "https://media.api-sports.io/football/teams/20.png"
},
"points": 1,
"goalsDiff": -3,
"group": "FIFA World Cup: Group C",
"form": "LLL",
"status": "same",
"description": null,
"all": {
"played": 3,
"win": 0,
"draw": 1,
"lose": 2,
"goals": {
"for": 2,
"against": 5
}
},
"home": {
"played": 1,
"win": 0,
"draw": 0,
"lose": 1,
"goals": {
"for": 0,
"against": 2
}
},
"away": {
"played": 2,
"win": 0,
"draw": 1,
"lose": 1,
"goals": {
"for": 2,
"against": 3
}
},
"update": "2020-06-18T00:00:00+00:00"
}
],
The code display the data in the datatable
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<Standings>(
future: _apiService.getStandings(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
Standings datas = snapshot.data;
return ListView.builder(
itemCount: datas.response[0].league.standings.length,
itemBuilder: (BuildContext ctx, int i) {
return Card(
child: DataTable(
// ignore: prefer_const_constructors
// ignore: prefer_const_literals_to_create_immutables
// ignore: prefer_const_constructors
columns: <DataColumn>[
DataColumn(
label: Text('Team'),
),
],
rows: <DataRow>[
DataRow(
cells: <DataCell>[
DataCell(
Text(datas.response[0].league.standings[0][0]
.team.name),
),
],
),
],
),
);
});
}
return Center(
child: CircularProgressIndicator(),
);
}),
));
The result
Result when ran code
I know the reason one team is showing is because of this code
<DataCell>[
DataCell(
Text(datas.response[0].league.standings[i][0]
.team.name),
),
But how can I display the rest of teams automatically? Thanks in advance.
For anyone that was facing the same problem, based on this question(Link) that was answered, this help me modified the code.
return ListView.builder(
itemCount: datas.response[0].league.standings.length,
itemBuilder: (BuildContext ctx, int i) {
return Column(
children: <Widget>[
ListTile(
title: Text(
datas.response[0].league.standings[i][0].group),
),
Row(
children: [
Text('Position'),
Text(''),
Text('Team'),
],
),
Card(
child: Row(
children: <Widget>[
Column(
children: <Widget>[
Text(datas
.response[0].league.standings[i][0].rank
.toString()),
Text(datas
.response[0].league.standings[i][1].rank
.toString()),
Text(datas
.response[0].league.standings[i][2].rank
.toString()),
Text(datas
.response[0].league.standings[i][3].rank
.toString()),
],
),
Column(children: <Widget>[
Image(
image: NetworkImage(datas.response[0].league
.standings[i][0].team.logo),
height: 30,
width: 20,
),
Image(
image: NetworkImage(datas.response[0].league
.standings[i][1].team.logo),
height: 30,
width: 20,
),
Image(
image: NetworkImage(datas.response[0].league
.standings[i][2].team.logo),
height: 30,
width: 20,
),
Image(
image: NetworkImage(datas.response[0].league
.standings[i][3].team.logo),
height: 30,
width: 20,
),
]),
Column(
children: [
Text(datas.response[0].league.standings[i][0]
.team.name),
Text(datas.response[0].league.standings[i][1]
.team.name),
Text(datas.response[0].league.standings[i][2]
.team.name),
Text(datas.response[0].league.standings[i][3]
.team.name)
],
)
],
),
)
],
);
});
I have this response coming from an API ...
{
"current_page": 1,
"data": [
{
"id": 1,
"category_id": 1,
"creator_id": 1,
"instructor_id": 1,
"difficulty_id": 1,
"status_id": 1,
"title": "hebae",
"overview": "Course Overview",
"deleted_at": null,
"created_at": "2020-01-02 15:16:08",
"updated_at": "2020-01-02 15:16:08"
},
{
"id": 2,
"category_id": 1,
"creator_id": 1,
"instructor_id": 2,
"difficulty_id": 1,
"status_id": 1,
"title": "update course 1",
"overview": "Course Overview",
"deleted_at": null,
"created_at": "2020-01-02 15:18:40",
"updated_at": "2020-01-02 15:19:06"
},
{
"id": 3,
"category_id": 1,
"creator_id": 1,
"instructor_id": 1,
"difficulty_id": 1,
"status_id": 1,
"title": "hebaTest",
"overview": "Course Overview",
"deleted_at": null,
"created_at": "2020-01-02 15:24:09",
"updated_at": "2020-01-02 15:24:09"
},
{
"id": 4,
"category_id": 2,
"creator_id": 1,
"instructor_id": 1,
"difficulty_id": 1,
"status_id": 1,
"title": "hebaTest",
"overview": "Adile",
"deleted_at": null,
"created_at": "2020-01-02 15:25:03",
"updated_at": "2020-01-02 15:25:03"
},
{
"id": 5,
"category_id": 2,
"creator_id": 1,
"instructor_id": 1,
"difficulty_id": 1,
"status_id": 1,
"title": "hebaTest",
"overview": "Adile",
"deleted_at": null,
"created_at": "2020-01-02 15:33:06",
"updated_at": "2020-01-02 15:33:06"
},
{
"id": 6,
"category_id": 1,
"creator_id": 1,
"instructor_id": 1,
"difficulty_id": 1,
"status_id": 1,
"title": "Course Title",
"overview": "Course Overview",
"deleted_at": null,
"created_at": "2020-01-05 08:24:56",
"updated_at": "2020-01-05 08:24:56"
},
],
"first_page_url": "http://skillboardbackend-staging.zph2jwe3pc.eu-west-1.elasticbeanstalk.com/api/course?page=1",
"from": 1,
"last_page": 2,
"last_page_url": "http://skillboardbackend-staging.zph2jwe3pc.eu-west-1.elasticbeanstalk.com/api/course?page=2",
"next_page_url": "http://skillboardbackend-staging.zph2jwe3pc.eu-west-1.elasticbeanstalk.com/api/course?page=2",
"path": "http://skillboardbackend-staging.zph2jwe3pc.eu-west-1.elasticbeanstalk.com/api/course",
"per_page": 15,
"prev_page_url": null,
"to": 15,
"total": 29
}
I'm trying to get the "data" array to be defined as "categories" object, and the rest data can stay the same, how to do that with normalizr?
I tried this ...
const { data } = await apiGetAllCategories();
const dataSchema = new schema.Entity("categories");
const coursesSchema = new schema.Entity("info", {
data: [dataSchema]
});
const normalizedData = normalize(data, coursesSchema);
console.log(normalizedData);
But it always gives me the "info" as undefined, and the "result" as undefined ...
What am I doing wrong here?
Your data appears to already be in some reduced/normalized form as I don't see any nested, or repeated data structures. I think a simple array::reduce on your data is sufficient for your needs.
// Reduce data array to map [element.id => element]
const dataObject = data.reduce((dataObject, item) => {
dataObject[item.id] = item;
return dataObject;
}, {});
const data = [
{
id: 1,
category_id: 1,
creator_id: 1,
instructor_id: 1,
difficulty_id: 1,
status_id: 1,
title: "hebae",
overview: "Course Overview",
deleted_at: null,
created_at: "2020-01-02 15:16:08",
updated_at: "2020-01-02 15:16:08"
},
{
id: 2,
category_id: 1,
creator_id: 1,
instructor_id: 2,
difficulty_id: 1,
status_id: 1,
title: "update course 1",
overview: "Course Overview",
deleted_at: null,
created_at: "2020-01-02 15:18:40",
updated_at: "2020-01-02 15:19:06"
},
{
id: 3,
category_id: 1,
creator_id: 1,
instructor_id: 1,
difficulty_id: 1,
status_id: 1,
title: "hebaTest",
overview: "Course Overview",
deleted_at: null,
created_at: "2020-01-02 15:24:09",
updated_at: "2020-01-02 15:24:09"
},
{
id: 4,
category_id: 2,
creator_id: 1,
instructor_id: 1,
difficulty_id: 1,
status_id: 1,
title: "hebaTest",
overview: "Adile",
deleted_at: null,
created_at: "2020-01-02 15:25:03",
updated_at: "2020-01-02 15:25:03"
},
{
id: 5,
category_id: 2,
creator_id: 1,
instructor_id: 1,
difficulty_id: 1,
status_id: 1,
title: "hebaTest",
overview: "Adile",
deleted_at: null,
created_at: "2020-01-02 15:33:06",
updated_at: "2020-01-02 15:33:06"
},
{
id: 6,
category_id: 1,
creator_id: 1,
instructor_id: 1,
difficulty_id: 1,
status_id: 1,
title: "Course Title",
overview: "Course Overview",
deleted_at: null,
created_at: "2020-01-05 08:24:56",
updated_at: "2020-01-05 08:24:56"
}
];
// Reduce data array to map [element.id => element]
const dataObject = data.reduce((dataObject, item) => {
dataObject[item.id] = item;
return dataObject;
}, {});
console.log(dataObject);
For anyone interested in how to normalize this response with "normalizr", I figured out where I went wrong, and that normalizr usually looks for and an "id" key at the top level, and if it can't find that you gonna have to provide it, in my case there was no "id" on the top-level object, so I gave it the "per_page" as an id to make it work ...
const dataSchema = new schema.Entity("data");
const coursesSchema = new schema.Entity( "info",
{
data: [dataSchema]
}, { idAttribute: "per_page" } );
const normalizedData = normalize(data, coursesSchema);
By the way the "answer" provided by #Drew Reese is way simpler and cleaner in this kind of flat object response that I got.
Cheers :)
I've got ES index products with data like this (simplified version, there are about 20 fields actually):
{_id: 1, _score: 1, color: red, size: S}
{_id: 2, _score: 1, color: red, size: M}
{_id: 3, _score: 1, color: red, size: L}
{_id: 4, _score: 1, color: blue, size: S}
{_id: 5, _score: 1, color: blue, size: M}
{_id: 6, _score: 1, color: blue, size: L}
I want to filter products by attributes (color and size) but I need all of them be presented in results, the filter condition should affect only scores. Examples:
Query: color == red
Result:
{_id: 1, _score: 1}
{_id: 2, _score: 1}
{_id: 3, _score: 1}
{_id: 4, _score: 0}
{_id: 5, _score: 0}
{_id: 6, _score: 0}
Query: size == M
Result:
{_id: 1, _score: 0}
{_id: 2, _score: 1}
{_id: 3, _score: 0}
{_id: 4, _score: 0}
{_id: 5, _score: 1}
{_id: 6, _score: 0}
Query: color == red && size == M
Result:
{_id: 1, _score: 0}
{_id: 2, _score: 1}
{_id: 3, _score: 0}
{_id: 4, _score: 0}
{_id: 5, _score: 0}
{_id: 6, _score: 0}
Any ideas how can I achieve that? Does it look like work for elasticsearch? Maybe I should consider to switch some other store/database.
ES version is 1.7.5
I am not sure what your use case is but this is not something I would recommend that you do trying to fix your relevancy score. Here is an example for one of the cases and there are multiple ways of doing this
POST /_search
{
"query":{
"bool":{
"should":[
{
"constant_score":{
"filter":{
"term":{
"color":"red"
}
},
"boost":1
}
},
{
"bool":{
"must_not":{
"term":{
"color":"red"
}
},
"boost":0
}
}
]
}
}
}
and the result is
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 6,
"max_score": 1,
"hits": [
{
"_index": "test",
"_type": "_doc",
"_id": "2",
"_score": 1,
"_source": {
"color": "red",
"size": "M"
}
},
{
"_index": "test",
"_type": "_doc",
"_id": "1",
"_score": 1,
"_source": {
"color": "red",
"size": "S"
}
},
{
"_index": "test",
"_type": "_doc",
"_id": "3",
"_score": 1,
"_source": {
"color": "red",
"size": "L"
}
},
{
"_index": "test",
"_type": "_doc",
"_id": "5",
"_score": 0,
"_source": {
"color": "blue",
"size": "M"
}
},
{
"_index": "test",
"_type": "_doc",
"_id": "4",
"_score": 0,
"_source": {
"color": "blue",
"size": "S"
}
},
{
"_index": "test",
"_type": "_doc",
"_id": "6",
"_score": 0,
"_source": {
"color": "blue",
"size": "L"
}
}
]
}
}
$scope.openingtimes= {
"1": {"id": 1, "day": 1, "name_of_day": "Pondělí", "open_from": "13:00", "open_to": "16:00"},
"5": {"id": 5, "day": 1, "name_of_day": "Pondělíadas", "open_from": "13:00", "open_to": "16:02"},
"7": {"id": 7, "day": 1, "name_of_day": "Pondělí", "open_from": "13:00", "open_to": "16:00"},
"9": {"id": 9, "day": 1, "name_of_day": "Pondělísf", "open_from": "13:00", "open_to": "16:00"},
"10": {"id": 10, "day": 1, "name_of_day": "Pondělí", "open_from": "13:00", "open_to": "16:00"},
"11": {"id": 11, "day": 1, "name_of_day": "Pondělí", "open_from": "13:00", "open_to": "16:00"},
"12": {"id": 12, "day": 1, "name_of_day": "Pondělí", "open_from": "13:02", "open_to": "16:00"},
"13": {"id": 13, "day": 1, "name_of_day": "Pondělí", "open_from": "13:00", "open_to": "16:00"}
};
problem with sorting because in view:
<div ng-repeat="time in openingTimes >
{{ time.id }}
</div>
Im getting this order: 1, 10, 11, 12, 13, 5, 7, 9 and this is ofcourse wrong. I can not change object it has to be same I know solution is make this:
$scope.openingtimes= {
1: {"id": 1, "day": 1, "name_of_day": "Pondělí", "open_from": "13:00", "open_to": "16:00"},
5: {"id": .....
but I can not do it. I tried something like:
<div ng-repeat="time in openingTimes | orderBy:'id*1'">
but it doesn't work. Doues anyone know how to make it sort like numbers? Thank you very much.
I finally found solution and it is how pankajparkar said filter like this:
app.filter('orderObjectBy', function() {
return function(items, field, reverse) {
var filtered = [];
angular.forEach(items, function(item) {
filtered.push(item);
});
filtered.sort(function (a, b) {
return (a[field] > b[field] ? 1 : -1);
});
if(reverse) filtered.reverse();
return filtered;
};
});
and VIEW:
<div ng-repeat="time in openingTimes | orderObjectBy:'id':false">
thanks for help!