Merge two Arrays using underscore.js in AngularJS - javascript

I have two api requests and both gets a result of JSON. The first request is "account" request and second is "Container" request. Now:
Request for all Accounts (accountid: 1, name: account1, blabla)
Request for all Containers (accountid: 1, name: Container1, blabla)
This is the result JSON of Accounts:
account: [
{
accountId: "123456789",
fingerprint: null,
name: "Account2",
path: "accounts/123456789",
},
This is the result JSON of Containers:
{
accountId: "123456789",
containerId: "123****",
domainName: null,
fingerprint: "123*****",
name: "Container23",
path: "accounts/123456789/containers/123******",
publicId: "GTM-****"
},
As you can see the container result contains the accountid so im trying to merge those two results so it becomes this combined (container):
{
accountId: "123456789",
name: "Account2", <------ THIS is what i want to merge
containerId: "123****",
domainName: null,
fingerprint: "123*****",
name: "Container23",
path: "accounts/123456789/containers/123******",
publicId: "GTM-****"
},
Remember there are many containers and accounts not just one block.
What i have tried using underscore:
var mergedList = _.map($scope.GTMcontainers, function(data){
return _.extend(data, _.findWhere($scope.account, { id: data.accountId }));
});
console.log(mergedList);
Here is my AngularJS
function getContainer() {
$http.get("http://******")
.then(function (response) {
$scope.GTMcontainers = response.data;
console.log(response);
$scope.loading = false;
})
.then(function () {
$http.get("http://******")
.then(function (response2) {
$scope.account = response2.data;
console.log(response2);
var mergedList = _.map($scope.GTMcontainers, function(data){
return _.extend(data, _.findWhere($scope.account, { id: data.accountId }));
});
console.log(mergedList);
})
})
}
Using this underscore gives me exactly the same JSON result as i requested (no merge).
Hope some one has experience with this.
Thanks
Updated:

using simple javascript
var accounts = [
{
accountId: "123456789",
fingerprint: null,
name: "Account2",
path: "accounts/123456789",
},{
accountId: "123456780",
fingerprint: null,
name: "Account3",
path: "accounts/123456789",
}]
var containers =[{
accountId: "123456789",
containerId: "123****",
domainName: null,
fingerprint: "123*****",
name: "Container23",
path: "accounts/123456789/containers/123******",
publicId: "GTM-****"
},{
accountId: "123456780",
containerId: "123****",
domainName: null,
fingerprint: "123*****",
name: "Container24",
path: "accounts/123456789/containers/123******",
publicId: "GTM-****"
}]
var result=[];
containers.forEach(function(item){
var temp=accounts.find(function(d){return d.accountId == item.accountId});
if(temp)
item.name = temp.name;
result.push(item);
})
console.log(result);

I have faced that issue, I knew I have got responses, but data was not merged. So I have used callbacks.
function getContainer(callback) {
$http.get("http://******")
.then(function (response) {
$scope.GTMcontainers = response.data;
console.log(response);
$scope.loading = false;
})
.then(function () {
$http.get("http://******")
.then(function (response2) {
$scope.account = response2.data;
console.log(response2);
if(response && response2){
callback(response,response2);
}
})
})
}
At function call time--
getContainer(function(array1,array2){
if(array1 && array2 && array1.length>0 && array2.length>0){
var mergedList = _.map(array1, function(data){
return _.extend(data, _.findWhere(array2, { id: data.accountId }));
});
console.log(mergedList);
}
})

Related

How to sort data with dynamic fields in PouchDB?

I'm having this query to index first_name and sort data according to it and it's working fine
try {
Users.createIndex({
index: { fields: ['first_name'] }
}).then(function (response) {
console.log(response);
}).catch(function (err) {
console.log(err);
});
const users = (await Users.find({
limit, skip: limit * (page - 1),
selector: {first_name: {$gt: null}},
sort: [ { 'first_name' : 'asc'} ]
})).docs;
But when I try to use variables it triggers an error
Error: Cannot sort on field(s) "orderBy" when using the default index
Code
orderBy = (query.params !== undefined && query.params.orderBy !== undefined) ? query.params.orderBy.sortField : 'first_name',
sortOrder = (query.params !== undefined && query.params.orderBy !== undefined) ? query.params.orderBy.sortOrder : 'asc'
console.log('orderBy: ' + orderBy) // first_name
console.log('sortOrder: ' + sortOrder) // asc
try {
Users.createIndex({
index: { fields: [orderBy] }
}).then(function (response) {
console.log(response);
}).catch(function (err) {
console.log(err);
});
const users = (await Users.find({
limit, skip: limit * (page - 1),
selector: {orderBy: {$gt: null}},
sort: [ { orderBy : sortOrder } ]
})).docs;
How can I edit this to make it work with dynamic variable just like the static variable?
The variable orderBy is not going to be substituted by value in the following code
selector: {orderBy: {$gt: null}},
sort: [ { orderBy : sortOrder } ]
The code evaluates orderBy literally. To assign a dynamic key to an object, use the object indexer:
myObject[myVar] = myVal;
Therfore in your code, something like this should do.
const query = {
selector: {},
sort: []
};
// setup selector
query.selector[prop] = {
$gt: null
};
// setup sort
let sortParam = {};
sortParam[prop] = sortDirection;
query.sort.push(sortParam);
I added a pouchDB snippet illustrating that concept.
let db;
// init example db instance
async function initDb() {
db = new PouchDB('test', {
adapter: 'memory'
});
await db.bulkDocs(getDocsToInstall());
}
initDb().then(async() => {
await db.createIndex({
index: {
fields: ['first_name']
}
});
await doQuery("first_name", "desc");
});
async function doQuery(prop, sortDirection) {
const query = {
selector: {},
sort: []
};
// setup selector
query.selector[prop] = {
$gt: null
};
// setup sort
let sortParam = {};
sortParam[prop] = sortDirection;
query.sort.push(sortParam);
// log the query
console.log(JSON.stringify(query, undefined, 3));
// exec the query
const users = (await db.find(query)).docs;
users.forEach(d => console.log(d[prop]));
}
// canned test documents
function getDocsToInstall() {
return [{
first_name: "Jerry"
},
{
first_name: "Bobby"
},
{
first_name: "Phil"
},
{
first_name: "Donna"
},
{
first_name: "Ron"
},
{
first_name: "Mickey"
},
{
first_name: "Bill"
},
{
first_name: "Tom"
},
{
first_name: "Keith"
},
{
first_name: "Brent"
},
{
first_name: "Vince"
},
]
}
<script src="https://cdn.jsdelivr.net/npm/pouchdb#7.1.1/dist/pouchdb.min.js"></script>
<script src="https://github.com/pouchdb/pouchdb/releases/download/7.1.1/pouchdb.memory.min.js"></script>
<script src="https://github.com/pouchdb/pouchdb/releases/download/7.1.1/pouchdb.find.min.js"></script>

How to delete multiple id documents in elasticsearch index

var elasticsearch = require('elasticsearch');
var client = new elasticsearch.Client({
host: 'ABC',
log: 'trace',
apiVersion: '7.1'
});
client.delete({
index: 'allevents',
type: '_doc',
id:"2"
}).then(function(resp) {
console.log("Successful query!");
console.log(JSON.stringify(resp, null, 4));
}, function(err) {
console.trace(err.message);
});
When I delete a single document by passing single id value.its working fine.
But I want to delete multiple documents in a single query.
How will we do?
I tried
client.delete({
index: 'allevents',
type: '_doc',
id: ["2","3"]
})
This function returning error.
I suggest to leverage the bulk method/API, like this:
var elasticsearch = require('elasticsearch');
var client = new elasticsearch.Client({
host: 'ABC',
log: 'trace',
apiVersion: '7.1'
});
var idsToDelete = ["2", "3"];
var bulk = idsToDelete.map(id => {
return {
'delete': {
'_index': 'allevents',
'_type': '_doc',
'_id': id
}
};
});
client.bulk({
body: bulk
}).then(function(resp) {
console.log("Successful query!");
console.log(JSON.stringify(resp, null, 4));
}, function(err) {
console.trace(err.message);
});
Another way of doing it is to leverage the deleteByQuery method/API:
var elasticsearch = require('elasticsearch');
var client = new elasticsearch.Client({
host: 'ABC',
log: 'trace',
apiVersion: '7.1'
});
var idsToDelete = ["2", "3"];
client.deleteByQuery({
index: 'allevents',
type: '_doc',
body: {
query: {
terms: {
_id: idsToDelete
}
}
}
}).then(function(resp) {
console.log("Successful query!");
console.log(JSON.stringify(resp, null, 4));
}, function(err) {
console.trace(err.message);
});

How can i calculate the response time in the below code and print it on the console

describe("Prefabs basic", function() {
it("It should create simple plrefab", function(done) {
var data = {
name: "Pre",
project: {
_id: settings.projectId,
name: "PM_40"
},
__t: "Prefabs",
stage: "planning",
multiTrade: {
value: false,
companies: []
},
owner: {
user: {
_id: ""
},
company: {
_id: ""
}
},
_customStage: "planning",
dates: [],
dateIndices: {
additional: {},
coord: 0,
deliver: 1
},
fileIndices: [],
todoIndices: [0],
new_prefab: true,
todos: [],
items: {
fileIndices: [],
todoIndices: [],
customId: "1",
name: "Item0",
level: "1",
zone: "west"
},
keywords: ["This is Prefab"]
};
chai
.request(server)
.post("/v3/prefabs/create")
.set("Authorization", settings.authKey)
.send(data)
.end(function(err, res) {
res.should.have.status(200);
prefab = res.body;
prefabId = res.body._id;
console.log(prefab);
});
});
});
I took the liberty of formatting your code so it is slightly more readable - in general you will get a better response to your questions if you present a question that is easy to understand. With that said, you can use process.hrtime() to time things in Node. For example,
it('does something', function() {
const startTime = process.hrtime();
chai
.request(server)
.post("/v3/prefabs/create")
.set("Authorization", settings.authKey)
.send(data)
.end(function(err, res) {
res.should.have.status(200);
const timeDifference = process.hrtime(startTime);
console.log(`Request took ${timeDifference[0] * 1e9 + timeDifference[1]} nanoseconds`);
});
});

How to access data on a `through` table with Bookshelf

I am using [BookshelfJS][bookshelfjs] for my ORM and am wondering how to access data on a though table.
I have 3 Models, Recipe, Ingredient and RecipeIngredient which joins the two.
var Recipe = BaseModel.extend({
tableName: 'recipe',
defaults: { name: null },
ingredients: function () {
return this
.belongsToMany('Ingredient')
.through('RecipeIngredient')
.withPivot(['measurement']);
}
}));
var Ingredient = BaseModel.extend({
tableName: 'ingredients',
defaults: { name: null },
recipes: function () {
return this
.belongsToMany('Recipe')
.through('RecipeIngredient');
}
}));
var RecipeIngredient = BaseModel.extend({
tableName: 'recipe_ingredients',
defaults: { measurement: null },
recipe: function () {
return this.belongsToMany('Recipe');
},
ingredient: function () {
return this.belongsToMany('Ingredient');
}
}));
I then attempt to retrieve a Recipe along with all the Ingredients however cannot work out how to access measurement on the RecipeIngredient.
Recipe
.forge({
id: 1
})
.fetch({
withRelated: ['ingredients']
})
.then(function (model) {
console.log(model.toJSON());
})
.catch(function (err) {
console.error(err);
});
Return:
{
"id": 1,
"name": "Delicious Recipe",
"ingredients": [
{
"id": 1,
"name": "Tasty foodstuff",
"_pivot_id": 1,
"_pivot_recipe_id": 1,
"_pivot_ingredient_id": 1
}
]
}
With no measurement value.
I had thought that the .withPivot(['measurement']) method would have grabbed the value but it does not return any additional data.
Have I missed something or misunderstood how this works?
I'm not exactly sure why you want to use through. If it's just a basic many-to-many mapping, you can achieve this by doing the following:
var Recipe = BaseModel.extend({
tableName: 'recipe',
defaults: { name: null },
ingredients: function () {
return this
.belongsToMany('Ingredient').withPivot(['measurement']);
}
}));
var Ingredient = BaseModel.extend({
tableName: 'ingredients',
defaults: { name: null },
recipes: function () {
return this
.belongsToMany('Recipe').withPivot(['measurement']);;
}
}));
You don't need an additional model for junction table. Just be sure to define a junction table in your database as ingredients_recipe (alphabetically joining the name of tables!). Or , you can provide your own custom name to belongsToMany function for what the junction table should be named. Be sure to have ingredients_id and recipe_id in ingredients_recipe
This is pretty much it. Then you can do
Recipe
.forge({
id: 1
})
.fetch({
withRelated: ['ingredients']
})
.then(function (model) {
console.log(model.toJSON());
})
.catch(function (err) {
console.error(err);
});

Mongoose, sort query by populated field

As far as I know, it's possible to sort populated docs with Mongoose (source).
I'm searching for a way to sort a query by one or more populated fields.
Consider this two Mongoose schemas :
var Wizard = new Schema({
name : { type: String }
, spells : { [{ type: Schema.ObjectId, ref: 'Spell' }] }
});
var Spell = new Schema({
name : { type: String }
, damages : { type: Number }
});
Sample JSON:
[{
name: 'Gandalf',
spells: [{
name: 'Fireball',
damages: 20
}]
}, {
name: 'Saruman',
spells: [{
name: 'Frozenball',
damages: 10
}]
}, {
name: 'Radagast',
spells: [{
name: 'Lightball',
damages: 15
}]
}]
I would like to sort those wizards by their spell damages, using something like :
WizardModel
.find({})
.populate('spells', myfields, myconditions, { sort: [['damages', 'asc']] })
// Should return in the right order: Saruman, Radagast, Gandalf
I'm actually doing those sorts by hands after querying and would like to optimize that.
You can explicitly specify only required parameters of populate method:
WizardModel
.find({})
.populate({path: 'spells', options: { sort: [['damages', 'asc']] }})
Have a look at http://mongoosejs.com/docs/api.html#document_Document-populate
Here is an example from a link above.
doc
.populate('company')
.populate({
path: 'notes',
match: /airline/,
select: 'text',
model: 'modelName'
options: opts
}, function (err, user) {
assert(doc._id == user._id) // the document itself is passed
})
Even though this is rather an old post, I'd like to share a solution through the MongoDB aggregation lookup pipeline
The important part is this:
{
$lookup: {
from: 'spells',
localField: 'spells',
foreignField:'_id',
as: 'spells'
}
},
{
$project: {
_id: 1,
name: 1,
// project the values from damages in the spells array in a new array called damages
damages: '$spells.damages',
spells: {
name: 1,
damages: 1
}
}
},
// take the maximum damage from the damages array
{
$project: {
_id: 1,
spells: 1,
name: 1,
maxDamage: {$max: '$damages'}
}
},
// do the sorting
{
$sort: {'maxDamage' : -1}
}
Find below a complete example
'use strict';
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/lotr');
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
let SpellSchema = new Schema({
name : { type: String },
damages : { type: Number }
});
let Spell = mongoose.model('Spell', SpellSchema);
let WizardSchema = new Schema({
name: { type: String },
spells: [{ type: Schema.Types.ObjectId, ref: 'Spell' }]
});
let Wizard = mongoose.model('Wizard', WizardSchema);
let fireball = new Spell({
name: 'Fireball',
damages: 20
});
let frozenball = new Spell({
name: 'Frozenball',
damages: 10
});
let lightball = new Spell({
name: 'Lightball',
damages: 15
});
let spells = [fireball, frozenball, lightball];
let wizards = [{
name: 'Gandalf',
spells:[fireball]
}, {
name: 'Saruman',
spells:[frozenball]
}, {
name: 'Radagast',
spells:[lightball]
}];
let aggregation = [
{
$match: {}
},
// find all spells in the spells collection related to wizards and fill populate into wizards.spells
{
$lookup: {
from: 'spells',
localField: 'spells',
foreignField:'_id',
as: 'spells'
}
},
{
$project: {
_id: 1,
name: 1,
// project the values from damages in the spells array in a new array called damages
damages: '$spells.damages',
spells: {
name: 1,
damages: 1
}
}
},
// take the maximum damage from the damages array
{
$project: {
_id: 1,
spells: 1,
name: 1,
maxDamage: {$max: '$damages'}
}
},
// do the sorting
{
$sort: {'maxDamage' : -1}
}
];
Spell.create(spells, (err, spells) => {
if (err) throw(err);
else {
Wizard.create(wizards, (err, wizards) =>{
if (err) throw(err);
else {
Wizard.aggregate(aggregation)
.exec((err, models) => {
if (err) throw(err);
else {
console.log(models[0]); // eslint-disable-line
console.log(models[1]); // eslint-disable-line
console.log(models[2]); // eslint-disable-line
Wizard.remove().exec(() => {
Spell.remove().exec(() => {
process.exit(0);
});
});
}
});
}
});
}
});
});
here's the sample of mongoose doc.
var PersonSchema = new Schema({
name: String,
band: String
});
var BandSchema = new Schema({
name: String
});
BandSchema.virtual('members', {
ref: 'Person', // The model to use
localField: 'name', // Find people where `localField`
foreignField: 'band', // is equal to `foreignField`
// If `justOne` is true, 'members' will be a single doc as opposed to
// an array. `justOne` is false by default.
justOne: false,
options: { sort: { name: -1 }, limit: 5 }
});

Categories

Resources