Result of multiple table query is array of non-array - javascript

The resulting data of a multiple table query (see http://www.breezejs.com/documentation/query-examples#Lookups) is not exactly what I expected. I expected an array (item for each table) of arrays (of entity fields). But, what I get is an array of sort-of arrays. The outer array is -- as expected -- filled with an item for each table. But, the inner objects are not typed as Array. They do actually have members named like indexed items (0, 1, 2, ...), but since it's not an array, I cannot use length or forEach. Is this a bug in Breeze?
Note that when I query for items from one table, the result is typed as array (of entity fields).
Here's my server code:
[HttpGet]
public object _Combo()
{
return new IOrderedQueryable[] { _contextProvider.Context.Company, _contextProvider.Context.Project, _contextProvider.Context.ProjectArea };
}
Here's my client code:
entityManager.executeQuery(breeze.EntityQuery.from("_Combo"))
.then(function (data) {
var companies = data.results[0];
//companies is not an array, but does have numbered members!
}).fail(queryFailed);

I'm not completely sure what "shape" you want returned from looking at your "_Combo" code? But if it is an anon type that contains Companies, Projects and ProjectAreas, then the following should work. You don't need to return a IQueryable unless you plan to have a client side filter applied on the server.
[HttpGet]
public object _Combo()
{
return new { Companies = ContextProvider.Context.Company.ToList(),
Projects = ContextProvider.Context.Project.ToList(),
ProjectAreas = ContextProvider.Context.ProjectAreas.ToList() }
}
This will return a single element array with its one item containing an object with three properties: "Companies", "Projects" and "ProjectAreas". Each of which is an array of the corresponding entities. All of these entities will have been added to the entityManager. Hope this helps.

Related

How to make a summary list of one column in a large CSV file?

I have 20,000 rows in a CSV which I have loaded using d3. Within this CSV there are roughly 4,000 unique category names (each being repeated across various numbers of rows).
I would like to make a list (an array or objects) of all the ~4,000 category names from my CSV, to be able to filter out categories that I do not want to work with.
See code and data sample below; the category column is called feature_id.
var rowConverter = function(d){
return{
event_date: parseTime(d.event_date),
claim_number: d.claim_number,
cause: d.cause,
detail_cause: d.detail_cause,
paid_total: parseFloat(d.paid_total),
feature_id: d.feature_id,
id: parseFloat(d.id)
};
}
d3.csv('claims_cwy.csv', rowConverter, function(dataset) {
console.log(dataset);
}
You can create an empty array, iterate over this dataset and for each iteration check this category if it exists. If not, add to the array. Something like:
const categories = []
dataset.forEach( item => {
if ( categories.indexOf(item.category) <= 0)
categories.push(item.category)
})
PS: I don't know which of this attributes in the row represents the category, it's not clear.
There are various ways to achieve what you want. If you want to keep it D3-ish you could make use of d3.set() which not only guarantees uniqueness of its values, but also allows you to provide an accessor to extract the categories' values, i.e. the field feature_id, from your data.
const categories = d3.set(dataset, d => d.feature_id);
Note, however, that this requires an additional loop through your data. As you claim to have a large set of data, you might want to do it step by step by adding to the set in the row converter function.
const categories = d3.set();
const rowConverter = function(d) {
categories.add(d.feature_id);
};
Whatever approach you prefer the unique category values are available by calling d3.values().

Trying to dynamically organize JSON object elements into different arrays based on values

This is the JSON I'm working with:
https://data.cityofnewyork.us/resource/xx67-kt59.json?$where=camis%20=%2230112340%22
I'd be dynamically making the queries using different data, so it'll possibly change.
What I'm essentially trying to do is to somehow organize the elements within this array into different arrays based on inspection_date.
So for each unique inspection_date value, those respective inspections would be put into its own collection.
If I knew the dates beforehand, I could easily iterate through each element and just push into an array.
Is there a way to dynamically create the arrays?
My end goal is to be able to display each group of inspections (based on inspection date) using Angular 5 on a webpage. I already have the site up and working and all of the requests being made.
So, I'm trying to eventually get to something like this. But of course, using whatever dates in the response from the request.
2016-10-03T00:00:00
List the inspections
2016-04-30T00:00:00
List the inspections
2016-04-12T00:00:00
List the inspections
Just for reference, here's the code I'm using:
ngOnInit() {
this.route.params.subscribe(params => {
this.title = +params['camis']; // (+) converts string 'id' to a number
this.q.getInpectionsPerCamis(this.title).subscribe((res) => {
this.inspectionList = res;
console.log(res);
});
// In a real app: dispatch action to load the details here.
});
}
I wish I could give you more info, but at this point, I'm just trying to get started.
I wrote this in jQuery just because it was faster for me, but it should translate fairly well to Angular (I just don't want to fiddle with an angular app right now)
Let me know if you have any questions.
$(function() {
let byDateObj = {};
$.ajax({
url: 'https://data.cityofnewyork.us/resource/xx67-kt59.json?$where=camis%20=%2230112340%22'
}).then(function(data) {
//probably do a check to make sure the data is an array, im gonna skip that
byDateObj = data.reduce(function(cum, cur) {
if (!cum.hasOwnProperty(cur.inspection_date)) cum[cur.inspection_date] = [];
//if the cumulative array doesn't have the inspection property already, add it as an empty array
cum[cur.inspection_date].push(cur);
//push to inspection_date array.
return cum;
//return cumulatie object
}, byDateObj);
//start with an empty object by default;
console.log(byDateObj);
}, console.error);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Fastest way to add to and get values from a list of objects

I'm just getting started with JavaScript objects. I'm trying to store catalog inventory by id and locations. I think a single object would look something like this:
var item = {
id: number,
locations: ["location1", "location2"]
};
I've started to read a bit about it but am still trying to wrap my head around it. Not sure what is the fastest way add new items to a list with a location, add a new location to an existing item, all while checking for dupes. Performance of getting the locations later isn't as critical. This is part of a process that is running thousands of checks to eventually get items by id and location, so performance is key.
Final question, I'm not even sure if it's possible to store this in local storage. From another similar question, I'm not sure.
Using lodash, something like this should work to determine if an item id exists and append either a new item to the array, or just add a new location:
var item = [{
id: 1,
locations: ["location1", "location2"]
},{
id: 2,
locations: ["location2", "location4"]
}];
function findItem(id){
return _.findIndex(item, function(chr) {
return chr.id == id;
});
}
function addItem(id,locations) {
var position = findItem(id);
if (position<0) {
item.push({
id: id,
locations: locations
})
} else {
item[position].locations = _.uniq(item[position].locations.concat(locations));
}
}
addItem(2,['location292']);
addItem(3,['location23']);
console.log(item);
What it basically does is to search the array of objects (item) for an id as the one we are passing to the addItem() function, if it is found we add the new locations array to the existing item, if not it's creating a new object with a new id and location.
You've asked a question that contains some tradeoffs:
The simplest and fastest way to retrieve a list of locations is to store them in an array.
The fastest way to check something for a duplicates is not an array, but rather a map object that maintains an index of the key.
So, you'd have to discuss more about which set of tradeoffs you want. Do you want to optimize for performance of adding a non-duplicate or optimize for performance of retrieving the list of locations. Pick one or the other.
As for localStorage, you can store any string in LocalStorage and you can convert simply non-reference objects to a string with JSON.stringify(), so yes this type of structure can be stored in LocalStorage.
For example, if you want to use the array for optimized retrieval, then you can check for duplicates like this before adding:
function addLocation(item, newLocation) {
if (item.locations.indexOf(newLocation) === -1) {
item.locations.push(newLocation);
}
}
Also, you can store an array of items in LocalStorage like this:
localStorage.setItem("someKey", JSON.stringify(arrayOfItems));
And, then some time later, you can retrieve it like this:
var arrayOfItems = JSON.parse(localStorage.getItem("someKey"));

Search for elements that have a particular attribute in array

One element of my mongo collection has the following schema (and represents one poker hand).
{
"players":
[
{"active":true,"seat":1,"stack":1769,"screenName":"schla"},
{"active":true,"seat":3,"stack":2000,"screenName":"galgegla"},
{"active":true,"seat":4,"stack":483,"screenName":"khrier"},
{"active":true,"seat":5,"stack":2813,"screenName":"frrou4535"},
{"active":true,"seat":6,"stack":4002,"screenName":"Guabounai"}
],
"rounds":[],
"gameNum":"1030564654564",
"time":"2013/12/21 21:12:03"
}
I'd like to search for all hands in my collection that have at least one time the player with screenName "galgegla" inside the players array.
Supposing your collection is called 'hands', you can do following:
db.hands.find( { 'players.screenName': 'galgegla' } )
See example under 'Match a Field Without Specifying Array Index' here: http://docs.mongodb.org/manual/tutorial/query-documents/#match-a-field-without-specifying-array-index
Try this:
a.filter(function(arr){
return arr.players.filter(function(player){
return player.screenName == 'galgegla';
}).length;
});
Assuming a is a array of those objects.
It filters the array of objects based on weather or not a filter on the object's players array returns any results.
... But of course I didn't consider mongo's native functionality, so the other answer'd be more effective. (But possibly not as efficient)

Is it possible to add multiple javascript objects with the same key to an associative array?

I am working on a Javascript web application (SPA) with RESTful api on the back-end. In my client-side datacontext I want to add objects to my model graph and then send the whole graph to server at once.
Suppose the following example:
I have a Person object in my model which itself has an array of say PhoneNumbers as a property. Now I load a Person from api for edditing and map it to my model. Suppose I want to add some phone number objects to my PhoneNumbers. For this I add each number e.g. {"id": 0, "number": 6536652226} with an id of zero to my client model and send the whole graph to server when user clicks save. In server I add the objects with the id of zero (new objects) to database with auto-incremented ids.
I am doing my project based on a tutorial. They do something like this to add objects to context:
var items = {},
// returns the model item produced by merging json obj into context
mapJsonToContext = function (json) {
var id = mapper.getJsonId(json);
var existingItem = items[id];
items[id] = mapper.fromDto(json, existingItem); //returns the mapped obj
return items[id];
},
add = function (newObj) {
items[newObj.id()] = newObj;
}
The problem is that if I use this method I wouldn't be able to remove by id the newly-added-not-yet-saved items in client-side 'cause all the ids are zero!
Any suggestions to fix this, or do I need a totally different approach?
First of all, two little misconceptions I've spot:
1) Forget about "associative arrays". Numeric arrays are the only kind arrays you have; the other constructs are just "objects" (this is not PHP).
2) If it's JSON it's a string, not an object.
Other than that, you can of course use an arbitrary value to represent "new" (though I'd probably use null rather than 0) as soon as you don't use such value to uniquely identify the yet-to-add item. E.g., this is just fine:
[
{"id": 0, "number": "6536652226"},
{"id": 0, "number": "9876543210"},
{"id": 0, "number": "0123456789"}
]
This is not:
// WRONG!!!!
{
0: "6536652226",
0: "9876543210",
0: "0123456789"
}
}
And of course you cannot find numbers by ID if they still don't have an ID. You need to choose:
Retrieve the generated ID from DB and update your local data
Delete by number
Create a localId property on newly created client-side objects, and use that as your key when reconciling server returned-data. Obviously the server would have to return this localId to you.

Categories