I'm having trouble fetching data on firebase with complex structure.
I have a structure like this:
place1: {
visits: {
user1: true,
user2: true,
user3: true,
user4: true
}
},
place2: {
visits: {
user1: true,
user3: true,
user4: true
}
},
place3: {
visits: {
user2: true,
user3: true,
user4: true
}
}
How do you query all the users that has been to all the places?
Thank you so much for your help!
Your current data structure allows you to efficiently fine all users that have been to a specific place. It does not allow you to efficiently query all places that a specific user has been to.
To allow that second query, you should add a second data structure:
user1: {
place1: true,
place2: true
},
user2: {
place1: true,
},
user3: {
place1: true,
place3: true
},
user4: {
place1: true,
place2: true,
place3: true,
place4: true
}
With this additional structure (often called an inverted index) in place, you can find the places each user went to.
Since you now have two structures, you will need to ensure you add each visit to both places. A single multi-location update can accomplish that:
function recordVisitor(uid, placeid) {
var updates = {};
updates[`/userVisits/${uid}/${placeid}`] = true;
updates[`placeVisitors/${placeid}/${uid}`] = true;
firebase.database().ref().update(updates);
}
Also see my answer for a related use-case (querying items in categories) that also requires an inverted index: http://stackoverflow.com/questions/40656589/firebase-query-if-child-of-child-contains-a-value
Related
The problem I am facing is that Sequelize doesn't return the affected rows when calling the Model.increment, it does the change, when I check the database I see that it worked, but I need to know the what are the affected rows.
My code looks like this:
// DB file
const SearchModel = sequelize.define(
"SearchModel",
{
ID: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
},
Name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
SearchesCounter: {
type: DataTypes.INTEGER,
defaultValue: 1,
},
},
{ tableName: "SearchHistory" }
);
// then I do the search in another file after exporting sequelize
await database.sync();
const searchModel = database.model("SearchModel");
let DBResults = await searchModel.increment("SearchesCounter", {
returning: true,
where: {
Name: {
[Op.or]: searches, // searches is array of strings
},
},
});
And instead of getting [Affected_Rows[], number of affected rows] I am getting [undefined, number of affected rows].
Any help?
maybe it's not your increment.
but your searches...
Instead using Op.or (if you want to use array)
use Op.in
so the code will look like
where: {
Name: {
[Op.in]: ['a', 'b'], // array of strings
},
},
or simple version
where: {
Name: ['a', 'b'] // array of key word
},
I'm trying to get the information about a user and include all the reservation he has done as well as the total sales.
I'm trying to add a before get hook and include both reservations and sales. When I include just one of these it gets the COUNT right, but when I add both, it actually counts reservations and sales and adds them together for each one.
get: [
authenticate("jwt"),
context => {
context.params.sequelize = {
include: [
{
association: "reservacion",
required: false,
attributes: [[Sequelize.fn("COUNT", Sequelize.col("reservacion.id")), "total_res"]]
},
{
association: "venta",
required: false,
attributes: [[Sequelize.fn("COUNT", Sequelize.col("venta.id")), "ventas"]]
}
]
};
return context;
}
],
If you use DISTINCT you should avoid the problem of accumulation of results
get: [
authenticate("jwt"),
context => {
context.params.sequelize = {
include: [
{
association: "reservacion",
required: false,
attributes: [[Sequelize.fn("COUNT", Sequelize.fn("DISTINCT", Sequelize.col("reservacion.id")), "total_res"]]
},
{
association: "venta",
required: false,
attributes: [[Sequelize.fn("COUNT", Sequelize.fn("DISTINCT", Sequelize.col("venta.id"))), "ventas"]]
}
]
};
return context;
}
],
Im using mongoose with a MongoDb. The test runs are saved with the current state they are in. I would like to get the open or running test runs and the last ten finished test runs.
How can this be achieved?
The query i have for now looks like this:
...
models.testRun.find()
.or([
{ isOpen: true },
{ isRunning: true },
{ $and: [{ isOpen: false }] } // missing statement to select 10 entries
])
.sort({
updatedAt: "descending"
})
.populate(populateQuery)
.exec((error, testRuns) => {
console.log(testRuns);
});
At the last $or entry i thought i can enter a $and query which selects the last ten test runs.
The schema of a test run looks like this
const testRunSchema = mongoose.Schema({
isOpen: {
type: Boolean,
required: true,
},
isRunning: {
type: Boolean,
required: true,
},
hasError: {
type: Boolean,
required: true,
},
}, { timestamps: true });
...
models.testRun.find()
.or([
{ isOpen: true },
{ isRunning: true },
{ $and: [{ isOpen: false }] } // missing statement to select 10 entries
])
.sort({
updatedAt: "descending"
}
.{ $limit : 10 })
.populate(populateQuery)
.exec((error, testRuns) => {
console.log(testRuns);
});
The above addition should work, unless something specific about Mongoose
How can I avoid showing both the foreignKey that sequelize creates and the eagerly fetched object through includes?
I have the following model structure:
FormEntry:
owner: User
createdBy: User
modifiedBy: User
formEntryData: [FormEntryData]
I modeled it after reading through SequelizeJS docs and came up with the following:
const User = sequelize.define('user', {
id: {
type: Sequelize.BIGINT(20),
field: 'user_id',
primaryKey: true
},
emailAddress: {
type: Sequelize.STRING(256),
field: 'email_address'
}
}, {
tableName: 'users',
timestamps: false
});
const FormEntryData = sequelize.define('formEntryData', {
id: {
type: Sequelize.BIGINT(20),
field: 'id',
primaryKey: true
},
entryId: {
type: Sequelize.BIGINT(20),
field: 'entry_id'
},
...
}, {
tableName: 'formEntryData',
timestamps: false
});
const FormEntry = sequelize.define('formEntry', {
id: {
type: Sequelize.BIGINT(20),
field: 'entry_id',
primaryKey: true
},
...
}, {
tableName: 'formEntries',
timestamps: false
});
I then need to create the associations to tie the models together and after a lot of trial and error I came up with the following:
FormEntry.hasMany(FormEntryData, {foreignKey: 'entry_id', as: 'FormEntryData'});
FormEntry.belongsTo(User, {foreignKey: 'created_by', as: 'CreatedBy'});
FormEntry.belongsTo(User, {foreignKey: 'modified_by', as: 'ModifiedBy'});
FormEntry.belongsTo(User, {foreignKey: 'owner', as: 'Owner'});
I then was able to query the data by doing the following:
FormEntry.findByPrimary(1472280, {
include: [
{
model: FormEntryData,
as: "FormEntryData"
},
{
model: User,
as: "CreatedBy"
},
{
model: User,
as: "Owner"
},
{
model: User,
as: "ModifiedBy"
}
]
})
Unfortunately, my results seem kind of repetitive as it seems to be including both the foreign key and the object that is eagerly fetched.
{
"id": 1472280,
...
"created_by": 26508, <-- repetitive (don't want this)
"modified_by": 26508, <-- repetitive (don't want this)
"owner": null, <-- repetitive (don't want this)
"FormEntryData": [
{
"id": 27164476,
"entryId": 1472280, <-- repetitive (but I want this one)
...
"entry_id": 1472280 <-- repetitive (don't want this)
},
...
],
"CreatedBy": { <-- repetitive (but I want this one)
"id": 26508,
"emailAddress": "swaraj.kler#greywallsoftware.com"
},
"Owner": null, <-- repetitive (but I want this one)
"ModifiedBy": { <-- repetitive (but I want this one)
"id": 26508,
"emailAddress": "swaraj.kler#greywallsoftware.com"
}
}
You need to exclude specified fields from the query
FormEntry.findByPrimary(1472280, {
include: [
{
model: FormEntryData,
as: "FormEntryData",
attributes: { exclude: ['entry_id'] }
},
{
model: User,
as: "CreatedBy"
},
{
model: User,
as: "Owner"
},
{
model: User,
as: "ModifiedBy"
}
],
attributes: { exclude: ['owner', 'created_by', 'modified_by'] }
})
I can use dijit.form.FilteringSelect to show the Dropdown box. But It requests all data from the store dojo.data.ItemFileReadStore at once that I Don't want. I want it to query the store with the current value of the textbox and show the Autocompleter options.
A more complete example as above but equals of valid. But in my case I use QueryReadStore
this.store = new dojox.data.QueryReadStore({
url: 'url',
sortFields : [{attribute: 'attribute', descending: true}],
requestMethod : "get"}
);
callSuggest : function(){
var fetch = {
query: {attribute: "*"},
queryOptions: {
ignoreCase: true,
deep: true
},
serverQuery: this.searchParam,
onComplete: dojo.hitch(this, function(result, dataObject){
//do something
}),
onError: function(errText){
console.error('error');
}
};
this.store.fetch(fetch);
},
You would have to perform something like this I assume,
itemStore .fetch({ query: { name: "pepper", aisle: "Spices" },
queryOptions: { ignoreCase: true }, onComplete: ... });
Please see this link for a complete listing and details.
http://dojotoolkit.org/reference-guide/quickstart/data/usingdatastores/filteringitems.html