MongoDb: Space in key name? - mongodb

I've got a bit of an issue that has caused me to bash my head against the wall for a couple of days.
Consider the following document:
{
'_id': '5d7de43ac7baaa0ff2c4ae2bd000518a',
'Some Complex Name': {
'data': {
'simpleKey': [
{
'name': 'Bob',
'age': 30
},
{
'name': 'Sam',
'age': 31
},
{
'name': 'George',
'age': 20
}
]
}
}
}
In my understanding of JavaScript, I have learned that I would refer to the 'Some Complex Name' in the following manner (from within the scope of a map function):
var stuff = this['Some Complex Name']
Building from that, I would be able to access the names with the following:
var names = [];
for (var i in this['Some Complex Name'].data.simpleKey) {
names.push(this['Some Complex Name'].data.simpleKey[i].name);
}
emit(this._id, names);
Unfortunately, I'm wrong somewhere on this, as I'm getting an error like this
"errmsg" : "exception: map invoke failed: JS Error: TypeError: this['Some Complex Name'] has no properties nofile_b:2"
Thus, my question: How would I /properly/ access the 'Some Complex Name' key?
A bonus would be some documentation to explain this.
Thanks!

Actually, I just found the answer and it's exactly what I suspected.
MongoDB/PyMongo: How to use dot notation in a Map function? was the same issue, and as it turns out I needed to filter my query to make sure Some Complex Name existed in the documents I was working with. This was accomplished via the query to mapReduce.

Related

How to find all the matches in a nested array with the _id with mongoose

This question may be easy for some of you but I can't get how this query works.
In the attached picture: https://i.stack.imgur.com/KzK0O.png
Number 1 is the endpoint with the query I can't get it to work.
Number 2 is the endpoint where you can see how I am storing the object match in the database.
Number 3 is the data structure in the frontend.
Number 4 is the Match mongoose model.
I am trying to get all the matches that have the _id I am sending by param in any of its members array.
I am trying it with $in, but I am not sure how this nested object array property query works.
I am very new at web development and this is quite difficult to me, any help would be highly appreciated, even some documentation for dummies, since I can't understand the one in the official site.
Thanks in advance
router.get("/profile/:_id", (req, res) => {
const idFromParam = req.params._id;
console.log("params", req.params._id);
Match.find({ match: [ { teams: [{ members: $in: [_id: idFromParam ] } ] ] }}).populate("users")
.then((response) => {
res.json(response);
console.log("response", response);
}) })
.catch((err) =>
res.status(500).json({ code: 500, message: "Error fetching", err })
);
});

How to target a field in Prisma and get a flat array of values rather than an array of objects

I just started using Primsa 2 so I am still a noob at this but all I am trying to do is create a flat array of strings(Array<number>) based on the values I get from a specific field. Right now when I target that field it gives me an array of objects like this: userIds: [{ issueId: 1, userId: 1 }]
All I want is the value I get from the userId key and the array to return like this userIds: [ 1 ]. I was able to fix this with some formatting code after the query which was done like so:
const issues = project.issues.map(issue => ({ ...issue, userIds: [...issue.userIds.map((id) => id.userId)] }))
const _project = { ...project, issues }
However, this doesn't seem like the most optimal solution. If this is the only way that is fine but I assume with the power that Prisma has for querying, this is something I can do just in the query alone?
For reference, my query currently looks like this:
const project = await prisma.project.findFirst({
where: { id: req.currentUser.projectId },
include: { users: true, issues: { include: { userIds: true } } },
})
Thanks in advance!
Can you show your schema? Perhaps you can model the relation differently. However, unless if you provide a field, userIds, that is a flat array and not a field of a an other relation it will be returned as a list of objects as you have already.

Mongoose: sort query results by least occurences of word in array

I have a collection of videos :
var VideoSchema = new mongoose.Schema({
url: {
type: String, required : true
},
orderBy: {
type: Number
},
views: [{
type: String
}]
});
'orderBy' lets me define the order in which I serve videos
'views' is a list of usernames, those who have watched the video.
I want to keep users from watching again the same video until they have watched all videos in the collection. So I keep the names of users who have watched the video inside the 'views'.
Now I query for videos using 'sort'.
return this.find(videoQuery)
.skip(offset)
.limit(count || 10) // #todo 10 : param
.sort({views: {$meta: username}, 'orderBy': -1})
.exec();
And I get the error message :
Can't canonicalize query: BadValue bad sort specification
Can you help ?
May be wrong but from mongo docs. When you specify $meta in sort you need to include it in projectedFieldName.
https://docs.mongodb.com/manual/reference/operator/projection/meta/#proj._S_meta
So it should looks something like this
return this.find(videoQuery, { views: { $meta: 'textScore' } })
.skip(offset)
.limit(count || 10) // #todo 10 : param
.sort({views: {$meta: textScore}, 'orderBy': -1})
.exec();
UPDATED
Seems that $meta only accepts 'textScore' as #Pierre mentioned.
So another suggestion is to use underscore or native js to sort data when response comes from DB. This will be less efficient and may need some adjustments, but this will work definitely.
Hope this helps.

Waterline find model where RegExp

I'm trying to create a simple search-function in SailsJS (beta), using the waterline ORM for data handling. My function in my controller does the search using the predefined find()-method of waterline.
I wonder, is it possible to send an SQL-regexp pattern to the waterline find()-function to make it fetch all users having a matching REGEXP?
My find-method in my controller contains this (except the regexp functionality, which I'm asking for):
// Replace any spaces with SQL regex wildcards
var regexp = req.body.search.replace(' ', '*');
// Show found users
User.find()
.where({
or: [
{username: { contains: req.body.search }},
{email: { contains: req.body.search }},
{fullName: { regexp: regexp }}
]
}).exec(function(err, users){
if (err){
return res.send(403, 'Failed to find users' + JSON.stringify(err));
}
res.view('userlist', {
users: users
});
});
The fullName attribute is defined as an instance method within the attributes, and is probably not searchable. However, is there a way to make a decent search for names?
This is an extract from my User model:
module.exports = {
attributes: {
firstName: {
type: 'string'
},
lastName: {
type: 'string'
},
fullName: function(){
return this.firstName + ' ' + this.lastName;
},
(...some more attributes, as well as email and username...)
}
}
How do i make the find()-method work with SQL regex? My goal is to make a search for "Hans Eikerol" display "Hans Martin Eikerol" in the result set.
Author Edit:
Thanks for the answer:) However, I managed to find a suitable solution to my problem without having to use regex pattern search. This is my new controller method:
var split = req.body.search.split(' ');
// Assume last piece of search is the lastName, ignore middlenames
var firstName = split[0];
var lastName = split.pop();
// Show found users
User.find()
.where({
or: [
{username: { contains: req.body.search }},
{email: { contains: req.body.search }},
{firstName: { contains: firstName }},
{lastName: { contains: lastName }},
{firstName: {startsWith: firstName}, lastName: lastName}
]
}).exec(function(err, users){
if (err){
return res.send(403, 'Failed to find users' + JSON.stringify(err));
}
res.view('admin/users', {
users: users
});
});
Waterline maps .find() to the underlying find syntax for the database you're connected to. It doesn't support regular expressions because regex is not supported by all of the database adapters. One could argue that since regular expression search comes standard with most mainstream databases these days, that the feature might have a place in Waterline, but in the meantime you can use .query to do a native SQL query. Then you coerce the results back to Waterline models. For example, with sails-mysql:
User.query("[some sql query using RLIKE]", function(err, rows) {
if (err){
return res.send(403, 'Failed to find users' + JSON.stringify(err));
}
res.view('userlist', {
// Map the rows returned by the query to Waterline instances
users: rows.map(function(row){return new User._model(row);});
});
});
thanks a lot for your answer, I have implemented something like this, using waterline on sails:
.find({ $and:[{"userType":"basic"},{"name":{contains:req.params.name}} ] })
.exec(function(err,seller){
if(err){
res.send(err);
}else{
console.log(seller);
res.send(seller)
}
})

Building a dynamic mongo query for meteor

I'm building an app that has clickable 'filters'; I'm creating a list of objects(?) that I want to pass to a mongo 'find', so that I can pull out listings if selected attributes match a certain score.
My data is structured like this (a snippet):
name: 'Entry One',
location: {
type: 'Point',
coordinates: [-5.654182,50.045414]
},
dogs: {
score: '1',
when: 'seasonal',
desc: 'Dogs allowed from October to April'
},
lifeguard: {
score: '1',
when: 'seasonal',
desc: 'A lifeguard hut is manned between April and October',
times: ''
},
cafe: {
score: '1',
name:'Lovely cafe',
open:'seasonal'
}, ...
My search variable is a list of objects (I think?) that I assign to a session variable. If I output this session var ('searchString') via JSON.stringify, it looks like this:
{"cafe":{"score":"1"},"dogs":{"score":"1"}}
I'd like to pass this to my mongo find so that it only lists entries that match these scores on these attributes, but it's returning zero results. Do I need to somehow make this an $and query?
Currently it looks like this:
Beaches.find(searchString);
Unfortunately as soon as I drop searchString into the find, I get zero results even if it's empty {}. (When it's just a find() the entries list fine, so the data itself is ok)
What am I doing wrong? I'm relatively new to mongo/meteor, so I apologise in advance if it's something stupidly obvious!
Don't stringify the query. Flatten the object instead. Example:
Beaches.find({
"cafe.score": 1,
"dogs.score": 1,
});