Kohana 3 (ORM or DB) returning single field - kohana-3

What is the best way to retrieve results from one field using DB or ORM?
For example, I need an array of user's friends ids to pass them to other function. I'm currently doing it like this:
$friends_ids = $this->friends->find_all()->as_array('id', 'name');
$friends = array();
foreach ($friends_ids as $k => $v)
{
array_push($friends, $k);
}
Maybe there's a better way?

$friends = $this->friends->find_all()->as_array(NULL, 'id');

Related

Make a mongoDB query using OR statement and array

I have web interface need to access an URL (shown below) and return only results with requested groups:
http://localhost:3000/device/getgroups/group1,group2,group3,group4
In MongoDB I have entries with the field 'loc_group'.
I want to return the results only where have the field "loc_group" = group1 OR group2 OR group3 OR group4.
My routes are like this:
router.get('/getgroups/:groups', async (req, res) => {
try {
var groups = "req.parms.groups";
#split groups
var arr = groups.split(",");
#iterate in the results on array (arr)
for (var i = 0; i < arr.length; i++) {
arr[i] = ++arr[i];
if (i = arr.lenght) {
var query = "{'loc_group': '" + arr[i] + "' }"
var totals = totals + query;
} else {
var query = "{'loc_group': '" + arr[i] + "' },"
var totals = totals + query;
}
}
# after this for, the totals must looks like
# "{'loc_group': 'group1' }"
# "{'loc_group': 'group2' }"
# "{'loc_group': 'group3' }"
# "{'loc_group': 'group4' }"
#
# then i try to use it on the mongodb query:
const logues = await device.find({ $or: [ totals ], })
res.json(logues)
} catch (err) {
res.status(500).json({ message: err.message })
}
})
but it's not working, what I get when enter the URL is:
{"message":"$or/$and/$nor entries need to be full objects"}
I am a beginner to nodejs and this is my first question here, if need some other information or something please let me know. Thanks.
There are several issues with your code. But the main one is basically ignoring the expectations of API you work with. See, MongoDB expects regular JavaScript objects passed in $or query. What you give it instead is a concatenation of stringified objects, each created by this expression:
var query = "{'loc_group': '" + arr[i] + "' }"
... passed into regular array. Apparently, MongoDB couldn't guess what you wanted, hence $or/$and/$nor entries need to be full objects error.
So, instead of doing JS work on your own, just use native objects to create a query. In fact, you don't even need $or here, as you're looking for the same property's values. Quoting the docs:
When using $or with that are equality checks for the
value of the same field, use the $in operator instead of the $or
operator.
So here's one (simplified) way to do it:
router.get('/getgroups/:groups', async (req, res) => {
const locGroups = req.params.groups.split(',');
const logues = await device.find({ loc_group: { $in: locGroups } });
res.json(logues);
}
What? Yes, that's essentially it. You might consider adding some validation and error handling to this code, and may be some logging, too, but it should be a middleware concern anyway, so the controller stays THAT simple. And that's the beauty - and the reason of existence - of the modern backend-oriented ecosystems: easy things should stay easy.

Using NodeJS with monobd ($all function)

I am implementing a search by keywords with mongodb and node JS, but I see that there is the operator $all in Mongo that selects the documents where the field holds an array and contains all elements.
Here is my source code with node JS
exports.find = function(req, res) {
var b=req.params.search;
var query = {};
var cadsrch = b.split(' ');
var l = cadsrch.length;
var i = 0;
for (i = 0; i < l; i++) {
if(cadsrch[i]!=''){
query[i]=new RegExp('^'+cadsrch[i], 'i');
}
}
db.collection('publicacion', function(err, collection) {
collection.find({tags: {'$all':query}},{title:true,content:true}).limit(5).toArray(function(err, items) {
res.jsonp(items);
});
});
};
The above source does not work, but this query works in Mongo->
db.publication.find({tags:{$all:['chevrolet','car']}})
and the strange thing is with '$in' instead '$all' works, but it would be useful to work with '$all' to implement exact searches
The query below is working because you're not using Regexp in the $all array:
db.publication.find({tags:{$all:['chevrolet','car']}})
I believe adding RegExp into $all is forcing the query to find an array element that contains all of your expressions together.
For example, execute below:
db.publicacion.find({"tags": {$all: [/chevrolet/i, /car/i]}})
This will not return any result because it will search for a tag that contains both chevrolet and car keywords into a single string like: ["chevrolet-cars", "chevrolet-car", "carchevrolet", "chevroletcar"].
If you want to use multiple RegExp to find the documents that have similar tags, use Mongoose Aggregate functions: https://mongoosejs.com/docs/api/aggregate.html

NodeJS/Mongoose - How to reference individual models after concatenation?

I am concatenating two models (Blogs and Events) so I can display all records from both collections in a single forEach loop:
const blogs = await Blog.find({});
const events = await Event.find({});
const blogsAndEvents = blogs.concat(events);
blogsAndEvents.forEach(function(blogOrEvent) { etc. etc.
However, within the forEach loop, in some cases, I want to still reference the original model it comes from, e.g. 'if Blog, title equals BLOG, if Event, title equals event). I have a workaround for this where I am using a unique field from each model to determine the underlying model, like this:
if (blogOrEvent.blogPost) {
title = "BLOG"
} elseIf (blogOrEvent.eventDate) {
title = "EVENT"
}
This approach doesn't seem very clean to me though as it relies on their being a unique field in each model. It there a better way I can access the original underlying model within the loop? Thanks.
With mongoose documents it can be distinctly verified which Model they belong to using instance of :
const blogs = await Blog.find({});
const events = await Event.find({});
const blogsAndEvents = blogs.concat(events);
blogsAndEvents.forEach(function (blogOrEvent) {
if (blogOrEvent instanceof Blog) {
title = "BLOG";
} else if (blogOrEvent instanceof Event) {
title = "EVENT";
}
});

how to pass fieldname dynamically in mogodb

I want to pass field name dynamically in Mondgodb while query the collection. e.g.
emp.ply = function(res,res) {
Employee.find({area: 'Plymouth'}).exec(function(err,PLY) {
res.render("../index", {resultset: PLY})
here I'm doing query on field name area which is hard code. Instead of i want to pass fieldname dynamically. How we can achieve it in nodeJS
So, conceptually you just need to build the query object before sending it to the .find() function. Perhaps something like this:
const query = {}
const fieldname = 'area'
const fieldvalue = 'Plymouth'
query[fieldname] = fieldvalue
Employee.find(query).exec((err, ply) => {
// do whatever
});
You could conceptually extract both fieldname and fielvalue from req.body or req.query depending on what you're doing.
If your code supports ES6 or (any latest browser except IE), we can do this:
emp.ply = function(res,res) {
let searchField = 'area'; // this can be anything dynamically
Employee.find({[searchField]: 'Plymouth'}).exec(function(err,PLY) {
res.render("../index", {resultset: PLY})
})
}
You can refer to MDN docs about Computed property names

Mongoose find not match ids from array which passed

I'm stuck in mongoose query. I've an array of ids as input, I want to search that array of ids in a database for matching elements. It returns perfect result after using $in in find query.
Now, I want that Ids from an array which is not found in the database. what is the best way to do it?
Please try to comment it.
Template.find({
_ids : [
"as6d87as67da7s8d87a87", // available in database
"as6dasd8sa9d8a9a9s8d7", // not-available in database
"6756asd5as6dsadghasd3", // available in database
]
}, function(err, result){
// Need result as "as6dasd8sa9d8a9a9s8d7", which is not matched. or in object.
// Can we do with `aggregate` query?
});
I think this makes what you want
var _ids = [
"as6d87as67da7s8d87a87",
"as6dasd8sa9d8a9a9s8d7",
"6756asd5as6dsadghasd3"
];
Template.find({
_ids : _ids
}, function(err, result){
var filteredResult = _ids.filter(currentId => !result.some(item => item._id.toString() == currentId));
});
Answer by David will work. The idea here is to compare _ids array with the _ids in the result and return the missing ones. Adding more code just for understanding purposes:
Push _id of result into a new array
Compare _ids and the new array to return missing elements
var resIDs = new Array();
for (var i = 0; i < result.length; i++) {
resIDs.push(result[i]._id.toString());
}
var resultFiltered =
_ids.filter(function (v) {
return !resIDs.includes(v.toString());
})

Resources