SQLite3- I have a users table and a songNodes table. A user can favorite songs, and a user can 'fork' songs. I have two separate junction tables that represent these unique by purpose but otherwise identical relationships.
Sequelize- The only way I know how to perform a junction query in sequelize is as follows-
var myForks = function(userId, callback) {
User.findOne({
where: {
id: userId
}
})
.then(function(userObj) {
userObj.getSongNodes() //this is where I need to specify
.then(function(stuff) { //a junction table
callback(stuff);
})
})
};
I have tried to research this extensively and I can not find a way to specify which junction table I want to use with the automatically generated function 'getSongNodes.' Any help/guidance would be greatly appreciated!
I guess you have three tables which names are User, Song, SongNode. You have to define associations between these.
You can define associations like the following lines;
models.User.belongsToMany(models.Song, {
"constraints": false,
"foreignKey": "userId",
"through": {
model: models.SongNode,
unique: false
}
});
models.Song.belongsToMany(models.User, {
"constraints": false,
"foreignKey": "songId",
"through": {
model: models.SongNode,
unique: false
}
});
After; you can use relations between models like this;
var myForks = function(userId, callback) {
User
.findOne({
"where": { "id": userId }
})
.then(function(user) {
user
.getSongNodes()
.then(function(songNodes) {
callback(songNodes);
});
});
};
or you can like this too;
var myForks = function(userId, callback) {
User
.findOne({
"where": { "id": userId },
"include": [Song]
})
.then(function(user) {
callback(user.Songs);
});
};
I hope it works
Related
I've got a MongoDB database collection called Dealers structured a bit like this:
{
... dealer info goes here like address etc,
"user_logins": [
{
"Username": "something",
... other stuff
}
]
},{
... next dealer etc...
I'm using Mongoose to try and query on the user_logins.Username using this:
Mongoose model
const myTest = mongoose.Schema({
Username: {
type: "String",
required: true
}
}, { collection: "Dealers" })
module.exports = mongoose.model("Dealer", myTest);
The query
Dealer.find({'user_logins.Username' : 'something'}, (err, result) => {
if (err) {
console.log(err);
} else {
res.json(result);
}
});
All the Username's are distinct. But instead of returning the one matching document, it seems to be returning the whole Dealers collection.
I followed this example.
https://kb.objectrocket.com/mongo-db/use-mongoose-to-find-in-an-array-of-objects-1206
What am I doing wrong please?
Thanks.
EDIT: It seems fine if I try to find something on the root level. EG. Company name, address etc. But if I try to query an imbedded array of objects, that's when it pulls the whole collection. I don't get it.
Found the answer.
My model was wrong. It needed to reflect the actual structure of my data, which does kind of make sense.
This worked:
const myTest = mongoose.Schema({
user_logins: [{
Username: {
type: "String",
required: true
}
}]
}, { collection: "Dealers" })
module.exports = mongoose.model("Dealer", myTest);
So when I query without attribute: exclude... it returns me the correct user, but when I insert that in the query it returns a completly different user. Here is the code that I'm inserting.
const user = await Users.findOne(
{
attributes: { exclude: ["password", "admin", "createdAt", "updatedAt"] },
},
{ where: { id: req.user.id } }
);
res.json({ user });
Any ideas why is this happening?
Thanks in advance
You'r passing the where condition to the second paramter, but according to the docs: https://sequelize.org/docs/v6/core-concepts/model-querying-finders/#findone
Model.findOne only has one parameter which is the query options.
Move your where condition into the object for the first parameter.
const user = await Users.findOne({
attributes: {
exclude: ["password", "admin", "createdAt", "updatedAt"],
},
where: { id: req.user.id },
});
res.json({ user });
We have a college project in CouchDB and I'm using node, I want to create a view that returns a number of all my documents by email.
I cannot find anything that works and I'm not sure what I'm missing, I tried a lot of different reduce functions and emit methods.
Thanks for any answers.
The documents have 2 fields, name and email
Do not use the db endpoint because the response field doc_count includes design documents along with other documents that may not have an email field.
A straight forward way to do this is with a view. The code snippet demonstrates the difference between db info doc_count and a view's total_rows using PouchDB. I'd guess there's probably more interesting uses for the index.
The design doc is trivial
{
_id: '_design/my_index',
views: {
email: {
map: function(doc) {
if (doc.email) emit(doc.email);
}.toString()
}
}
}
And the view query is very efficient and simple.
db.query('my_index/email', {
include_docs: false,
limit: 0
})
const gel = id => document.getElementById(id);
let db;
function setJsonToText(elId, json) {
gel(elId).innerText = JSON.stringify(json, undefined, 3);
}
async function view() {
// display db info
setJsonToText('info', await db.info());
// display total number or rows in the email index
const result = await db.query('my_index/email', {
include_docs: false,
limit: 0
});
setJsonToText('view', result);
}
// canned test documents
function getDocsToInstall() {
return [{
email: 'jerry#garcia.com',
},
{
email: 'bob#weir.com',
},
{
email: 'phil#lesh.com'
},
{
email: 'wavy#gravy.com'
},
{
email: 'samson#delilah.com'
},
{
email: 'cosmic#charlie.com'
},
// design doc
{
_id: '_design/my_index',
views: {
email: {
map: function(doc) {
if (doc.email) emit(doc.email);
}.toString()
}
}
}
]
}
// init example db instance
async function initDb() {
db = new PouchDB('test', {
adapter: 'memory'
});
await db.bulkDocs(getDocsToInstall());
};
(async() => {
await initDb();
await view();
})();
<script src="https://github.com/pouchdb/pouchdb/releases/download/7.1.1/pouchdb-7.1.1.min.js"></script>
<script src="https://github.com/pouchdb/pouchdb/releases/download/7.1.1/pouchdb.memory.min.js"></script>
<pre>Info</pre>
<pre id='info'></pre>
<div style='margin-top:2em'></div>
<pre>email view</pre>
<pre id='view'>
</pre>
You can use GET /{db}, which returns information about the specified database. This is a JSON object that contains the property doc_count.
doc_count (number) – A count of the documents in the specified database.
With Angular for example, this could be done with the following method:
async countDocuments(database: string): Promise<number> {
return this.http.get<any>(this.url('GET', database), this.httpOptions).toPromise()
.then(info => info['doc_count']);
}
Assumption:
Assuming that following documents are present in the Customers database:
[
{
"_id": "93512c6c8585ab360dc7f535ff00bdfa",
"_rev": "1-299289ee89275a8618cd9470733035f4",
"name": "Tom",
"email": "tom#domain.com"
},
{
"_id": "93512c6c8585ab360dc7f535ff00c930",
"_rev": "1-a676883d6f1b5bce3b0a9ece92da6964",
"name": "Tom Doe",
"email": "tom#domain.com"
},
{
"_id": "93512c6c8585ab360dc7f535ff00edc0",
"_rev": "1-09b5bf64cfe66af7e1134448e1a328c3",
"name": "John",
"email": "john#domain.com"
},
{
"_id": "93512c6c8585ab360dc7f535ff010988",
"_rev": "1-88e347af11cfd1e40e63920fa5806fd2",
"name": "Alan",
"email": "alan#domain.com"
}
]
If I understand your query correctly, then based on above data, You need below given result set.
{
"tom#domain.com": 2,
"alan#domain.com": 1,
"john#domain.com": 1
}
Solution:
In order to achieve above, Consider following design document containing a View which has Map and Reduce functions.
{
"_id": "_design/Customers",
"views": {
"by-email": {
"map": "function (doc) {
if(doc.email){
emit(doc.email, doc._id);
}
}",
"reduce": "_count"
}
},
"language": "javascript"
}
The above view function emits value of the key email of the document if the key exists in the document.
The reduce function _count is a built in reducer (provided by CouchDB) that does the counting logic.
Executing View Query:
In order to query this view, you need to: select the view function, mark reduce to be executed (as it is optional to run reduce) and set 1 as group level.
Here is how you can do it through the UI:
Result:
Here is the result given by above query:
[![result of map reduce query
Hope this helped.
For more details about other reduce functions and group level, please refer CouchDB documentation.
Cheers.
I'm having two tables user and group, a manytomany relation between them, thereofre a third table group_has_user
given a user I'm trying to remove some groups,
I tried :
Model.User.findOne({
where: {
"id": POST.id
},
include: [Model.Project]
}).then(function (user) {
user.Project.destroy({
where:{
"id": ids
}
})
})
where id is the user id and ids, is a list of groups that I wan to
remove
but this code doesn't works, project is undefined, and also I don't think that what I want could be done this way, can anyone help ?
You can get the Projects you want to remove and then call the generated removeProject method on each project you got:
Model.User.findOne({
where: {
"id": POST.id
},
include: [Model.Project]
}).then(function (user) {
Model.Projcet.find({
where: {
id: {
[Op.in]: ids
}
}
}).then(projectsToRemove => {
projectsToRemove.forEach(p => {
await user.removeProject(p);
})
})
})
Source: Official documentation
I'm using sequelize.js for ORM, and I have some questions while I use it.
Models looks like this
var Keyword = db.define('keyword', {
name: db.STRING,
});
var KeywordSearchableMap = db.define('keyword_searchable_map', {
keyword_id: db.INTEGER,
searchable: db.STRING,
searchable_id: db.STRING,
score: db.STRING,
});
var Searchable = db.define('searchable') {
name: db.STRING,
});
Keyword.belongsToMany(Searchable, {
through: {
model: KeywordSearchableMap,
},
foreignKey: 'keyword_id'
});
Searchable.belongsToMany(Keyword, {
through: {
model: KeywordSearchableMap,
},
foreignKey: 'searchable_id'
});
And I want to get 'Searchable' things by Keyword.getSearchables() order by 'score' field in 'KeywordSearchableMap'
Is there any methods to get sorted searchable objects?