reorder table columns in Keen.io - tablecolumn

I'm trying to figure out how to reorder the columns on a table built from an extraction query. Changing the order in the 'property_names' field does not affect the column order displayed. I would like it to show 'subjectivity_range' column BEFORE 'text' column.
My code is:
Keen.ready(function() {
var textq = new Keen.Query("extraction", {
event_collection: source,
timeframe: 'this_1_days',
refresh_rate: "28000",
property_names: ["subjectivity_range","text"],
order_by: {'subjectivity_range':'result','direction':'DESC'},
timezone:"US/Eastern"
});
.type('table')
.title('Subjectivity examples')
.prepare();
client.run(textq, function(err, res) {
textchart
.data(res)
.parseRequest(this)
.render();
});
});

https://github.com/keen/keen-dataviz.js#extraction-table-columns-order
/*
dummy event model
{
user: {
email: 'john#doe.com'
},
favourite_fruit: 'Avocado'
}
*/
const chart = new KeenDataviz({
container: '#some_container', // required
table: {
columns: ['favourite_fruit', 'user.email', 'keen.created_at'] // custom order of the columns
}
});
You can use AZ Sorting, for example - descending:
chartElement
.data(responseFromApi)
.sortGroups('desc')
.render();

Related

How to insert an array of ids with create function in node

I Have defined this mongoose schema in node
`const bookingSchema = new mongoose.Schema({
tour: [
{
type: mongoose.Schema.ObjectId,
ref: 'Tour',
required: [true, 'Booking must belong to Tours!'],
},
],
user: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: [true, 'Booking must belong to User!'],
},
price: {
type: Number,
required: [true, 'Booking must have a price'],
},
createdAt: {
type: Date,
default: Date.now(),
},
paid: {
type: Boolean,
default: true,
},
});
bookingSchema.pre(/^find/, function (next) {
this.populate('user').populate({
path: 'tour',
select: 'name',
});`your text`
});
Then when i try to create a booking i use the create function
await Booking.create({ tour, user, price });`
the tour param is an array of ids
but i get this error
"Booking validation failed: tour.0: Cast to [ObjectId] failed for value "["5c88fa8cf4afda39709c295a,5c88fa8cf4afda39709c2951"]" (type string) at path "tour.0"
I can do it with only one tour if the tour property wasnt an array of objects. My main issue is that a booking can be related to many tour objects in my database
*edit after some modifications the error become
"Unexpected token u in JSON at position 0"
My front end code(angular) is this. I am making a get request to my backend(node)
createBookingCheckout(params: any): Observable<any> {
console.log('serv');
return this.http.get<any>(`${CREATE_BOOKING_CHECKOUT}`, {
params,
withCredentials: true,
});
}
So i pass the ids as query param
And this is the backend where i am trying to create the booking
exports.createBookingCheckout = catchAsync(async (req, res, next) => {
const { order, tour: strTour } = req.query;
const user = req.user._id;
const parsedOrder = JSON.parse(order);
const tour = JSON.parse(strTour);
console.log(tour);
// const tours = await tour.forEach((id) => {
// Tour.find({ id });
// });
// console.log(tours);
let price = 0;
parsedOrder.forEach(
(obj) => (price = price + obj.price_data.unit_amount * obj.quantity)
);
if (!parsedOrder && !user) return next();
await Booking.create({ tour, user, price });
res.redirect(req.originalUrl.split('?')[0]);
res.status(200).json({
status: 'success',
});
});
I think the quick solution to this is that whenever you are going to add more than a tour you should create an array push all tours IDs to the array and then add the tourArray to the new Booking that you are going to create, and when you are going to update an existing Booking, you should repeat the process.
When you are going to create a new Booking document.
Scenario 1 : with one Tour
You just pass the id of the tour {always check if the tour exist}, that's obvious and simple, at the same time mongo is going to create a table referring to the model as Tour is defined as many within your Booking model
Scenario 2 : with more than one Tour
You need to define all the Tour's IDs in an array within the body
{
"tour": [ "id-1", "id-2", ...]
}
Updating a Booking
say that you are going to add a new Tour to an existing Booking,
Booking.findByIdAndUpdate(
{_id: id},
{
// ! here all your other data
$push: {tour: new_tour}
},
// this is just to return the updated booking
{new: true, runValidators: true}
}
=> the operator $push in mongoose is what you need to push into the existing array or tour that's already in your existing Booking
The new_tour is coming from your req.body
as for sure in some cases you are going to delete a Tour ID from a Booking,
=> in that case you are going to use the operator $pull

ExtJS - Grid filter with multiple columns and multiple values

I create a grid and a toolbar with Two Menu of menuCheckItem. When i check the menuCheckItem the grid filters even with multiple values and multiple columns.
This working fine, as I have created grid 1st and then the toolbar
this.up('') // Used Instead of Ext.getCmp()
Working FIDDLE - https://fiddle.sencha.com/#view/editor&fiddle/2lop
Now I am trying to create same toolbar along with Menu separately on top 1st and then create grid at below. But while doing this, nly Multiple values is working.
I am trying to filter grid with multiple values as well as multiple columns.
Few things i tried -
// Only Filters One Value at a time with each Columns
store.queryBy(function(record,id){
return (record.get('name') == someValue && record.get('phone') == otherValue);
});
and
// Filters Many Columns with Single Value
filter.add(
property : name, phone
value : "somevalue"
operator : "OR"
);
Is there any way to implement Toolbar 1st and then grid ? And Filter grid with many values and columns simultaneously ?
In this FIDDLE i remade a function(checkchange), which is universal , can be put separately and you'll be able to attach it to every menucheckitem you create. The only thing is that if you add new menucheckitem filter you should name the menucheckitem id with the name of the columnDataIndex-Menu and add this columnDataIndex in menuFilters and thats all.
checkchange: function (checkbox, checked, eOpts) {
var menuFilters = ['name', 'phone'];
var getChecked = function (m) {
var checkedItems = [];
m.items.items.forEach(function (c) {
if (c.checked) {
checkedItems.push(c.text);
}
});
return checkedItems;
};
//
var menus = new Map();
menuFilters.forEach(function (e) {
menus.set(e, Ext.getCmp(e + '-Menu'));
});
//
var fieldValues = [];
menuFilters.forEach(function (e) {
fieldValues.push([e, getChecked(menus.get(e))]);
});
//
var store = checkbox.up('grid').store;
store.clearFilter();
//
if (fieldValues.length > 0) {
store.filterBy(function (record) {
var fV = this.fieldValues;
for (var i = 0; i < fV.length; i++) {
if (fV[i][1].length > 0) {
if (fV[i][1].indexOf(record.get(fV[i][0])) === -1) {
return false;
}
}
}
return true;
}, {
fieldValues: fieldValues
});
}
}

Output all documents in mongoose

I am using mongoose ODM and have a schema which looks like this:
var banSchema = new Schema({
userid: { type: String, required: true, unique: true },
name: String,
groupid: String,
reason: String,
timestamp: Date
});
I want to output every single user id from all documents in the collection. I am using this query to obtain the userid objects. However I cannot seem to get the full list automatically. I have to manually enter the object number as seeen below:
bot.onText(/\/sync/i, function (msg) {
var fromId = msg.from.id;
var chatId = msg.chat.id;
if (fromId == config.sudo) {
console.log('Sudo Confirmed And Authorized!');
Ban.find({}, function (err, obj) {
console.log(obj[0].userid); // Returns A Single ID
console.log(obj[1].toObject().userid); // Returns a different ID
bot.sendMessage(chatId, obj[1].toObject().useridid);
});
} else {
console.log('Someone Is Trying To Act Like Sudo! *sigh*');
bot.sendMessage(chatId, 'You Are Not A Mod!');
}
});
This however does not return a full list of id's as I want. How could I solve this issue?
The code above is for a telegram bot which on a /sync command it should return a message with all ids from the collection.
Telegram bot API Limits
Due to the API limits, the entire output should be in a single message.
var query = Ban.find({}).select({
"userid": 1,
//Add more column fields here
"_id": 0 //Ensures _id is not displayed
});
var arr = [];
query.exec(function (err, results) {
if (err) throw err;
results.forEach(function (result) {
arr.push(result.userid);
// Add more column fields here;
});
var fixedJoin =arr.join("\n");
console.log(fixed);
bot.sendMessage(chatId, 'List\n\n' + fixedJoin);
});
The easiest way to get all values of a particular field across all docs in the collection is to use distinct:
Ban.distinct('userid', function (err, userids) {
// userids is an array containing all userid values in the collection.
// string.join into a single string for the message.
bot.sendMessage(chatId, 'USER IDs\n\n' + userids.join('\n'));
});
Use this syntax
Ban.find({}).
select('userid').
exec(function(err, result) {
//result is array of userid of all document
});
You can use this syntax:
Ban.find({}, 'userid', function(err, users) {
users.forEach(function(user) {
console.log(user);
bot.sendMessage(chatId, 'users \n' + user);
});
})

Is it possible to search for all keys that start with a certain prefix in Aerospike?

So I am looking to model our existing redis data into aerospike. One requirement that we have is to be able to get all the keys for a given user. For eg., say we have keys such as <id>:<timestamp>. Now, at some point in time, I need to get all keys for the given id, where I would require something like a prefix search across all keys in the aerospike namespace (which are indexed) to get the values for all <id>:<timestamp> keys. Would like to know if this is possible, and if yes, how.
You cannot do a query on key prefix directly. The server only stores the key digest, so the key value (<id>:<timestamp> in your case) doesn't get indexed.
The way to model this would be to add the <id> part of your key as a separate record bin. Then you can index that bin and run a query on it.
Here is a simple example - it's using the Aerospike Node.js client but the concept is the same no matter what client you prefer:
const Aerospike = require('aerospike')
const ns = 'test'
const set = 'demo'
// connect to cluster and create index on 'id' bin
var client = Aerospike.client()
client.connect((err) => {
assertOk(err, 'connecting to cluster')
createIndex('id', 'id_idx', Aerospike.indexDataType.STRING, () => {
// create a new sample record
var userId = 'user1'
var ts = new Date().getTime()
var key = new Aerospike.Key(ns, set, `${userId}:${ts}`)
var record = { id: userId, value: Math.random() }
client.put(key, record, (err) => {
assertOk(err, 'write record')
// query for records with matching 'id'
var query = client.query(ns, set)
query.where(Aerospike.filter.equal('id', userId))
var stream = query.foreach()
stream.on('error', (error) => assertOk(error, 'executing query'))
stream.on('end', () => client.close())
stream.on('data', (record, meta, key) => {
console.log(record)
})
})
})
})
function assertOk (err, message) {
if (err) {
console.error('ERROR: %s - %s', message, err)
process.quit()
}
}
function createIndex (bin, name, datatype, callback) {
var index = {
ns: ns,
set: set,
bin: bin,
index: name,
datatype: datatype
}
client.createIndex(index, (err, job) => {
assertOk(err, 'creating index')
job.waitUntilDone(100, (err) => {
assertOk(err, 'creating index')
callback()
})
})
}
Hope this helps!

ExtJS - Drag column header to other grid

I need keep the default feature of reordering columns and add
possibility drop the column in a second grid, building in the last a list
with the columns of first grid.
I hope has been clear.
I solved the issue extending DropZone. This implementation receive as constructor param the target grid, and this, be in the rbar (docked control) of source grid. The key is set ddGroup to "header-dd-zone-" plus id from source grid. I hope this is useful.
Ext.define('Crud.FilterDropZone', {
extend: 'Ext.dd.DropZone'
, constructor: function() {}
, init: function (grid) {
var me = this;
if (grid.rendered) {
me.grid = grid;
me.ddGroup = 'header-dd-zone-' + grid.up('grid').id;
grid.getView().on({
render: function(v) {
me.view = v;
Crud.FilterDropZone.superclass.constructor.call(me, me.view.el);
},
single: true
});
} else {
grid.on('render', me.init, me, {single: true});
}
}
, getTargetFromEvent: function (e) {
return {};
}
, onNodeDrop: function (nodeData, source, e, data) {
var header = data.header
, store = Ext.getCmp(e.target.id).getStore();
//store.add(new store.RecordType({ property: header.text, value: '', reference: header.dataIndex}));
store.add([[header.text, '', header.dataIndex]]);
}
});

Resources