Meteor: Global object not updating - mongodb

I am using Ionic 2 with meteor/MongoDB.
When I do the following, it inserts the chat object into the localChatCollection:
let promise: Promise<Mongo.Collection<Chat>> = this.findChats();
promise.then((data: Mongo.Collection<Chat>) => {
let localChatCollection: Mongo.Collection<Chat> = new Mongo.Collection<Chat>(null);
data.find().forEach(function (chat: Chat) {
console.log('==> ' + chat);
localChatCollection.insert(chat);
});
However, if I define the localChatCollection globally, it does not insert the chat object. There are no errors but the process just stops on the insert line.
private localChatCollection: Mongo.Collection<Chat> = new Mongo.Collection<Chat>(null);
....
this.localChatCollection.insert(chat);
Any ideas how I can get this to insert into a globally defined collection?

This works, but I don't think it is the most elegant solution:
let that = this;
data.find().forEach(function (chat: Chat) {
that.localChatCollection.insert(chat);
});

Related

Entity Framework 6: is it possible to update specific object property without getting the whole object?

I have an object with several really large string properties. In addition, it has a simple timestamp property.
What I trying to achieve is to update only timestamp property without getting the whole huge object to the server.
Eventually, I would like to use EF and to do in the most performant way something equivalent to this:
update [...]
set [...] = [...]
where [...]
Using the following, you can update a single column:
var yourEntity = new YourEntity() { Id = id, DateProp = dateTime };
using (var db = new MyEfContextName())
{
db.YourEntities.Attach(yourEntity);
db.Entry(yourEntity).Property(x => x.DateProp).IsModified = true;
db.SaveChanges();
}
OK, I managed to handle this. The solution is the same as proposed by Seany84, with the only addition of disabling validation, in order to overcome issue with required fields. Basically, I had to add the following line just before 'SaveChanges():
db.Configuration.ValidateOnSaveEnabled = false;
So, the complete solution is:
var yourEntity = new YourEntity() { Id = id, DateProp = dateTime };
using (var db = new MyEfContextName())
{
db.YourEntities.Attach(yourEntity);
db.Entry(yourEntity).Property(x => x.DateProp).IsModified = true;
db.Configuration.ValidateOnSaveEnabled = false;
db.SaveChanges();
}

send var js to django view in select dynamic

I am doing select dependent and I got a problem when making the query's, here the js
function cargar_paises() {
$.getJSON('cargar_paises', {}, function (data) {
$('#paises').empty();
$('#paises').append('<option value="0">Seleccione ...</option>');
$.each(data, function (id, desc) {
var option = $('<option></option>', {value:(id+1), text:desc});
$('#paises').append(option);
});
});
}
and my view
def cargar_paises(request):
if request.is_ajax:
pais = Pais.objects.all()
paises = []
for s in pais:
aux = []
id = s.pk
aux.append(id)
nombre = s.nombre
aux.append(nombre)
paises.append(aux)
return HttpResponse(json.dumps(paises), mimetype='aplication/json')
the problem is when I print the values ​​in the select and send the id to another query, the values ​​that I take are the index of the select and not the value of id_pais.
You can work this out a little better using a list of dictionaries instead of a list of lists, even using the dJango .values(), but to keep it simple, you ca use you exact same approach,
function cargar_paises() {
$.getJSON('cargar_paises', {}, function (data) {
$('#paises').empty();
$('#paises').append('<option value="0">Seleccione ...</option>');
$.each(data, function (item) {
var option = $('<option></option>', {value:item.id, text:item.nombre});
$('#paises').append(option);
});
});
}
and in the view,
def cargar_paises(request):
if request.is_ajax:
pais = Pais.objects.all()
paises = []
for s in pais:
aux = {}
aux['id'] = s.pk
aux['nombre'] = s.nombre
paises.append(aux)
return HttpResponse(json.dumps(paises), mimetype='aplication/json')
Remember, you can map Python dictionaries to Json objects, and python lists to Json arrays, another good hint is to use django-dajaxice it's a very good tool to do what you want, anyway is good to se this kind of things out of dJango.
Edit
I really thought about it, use the .values() in the query set, your view,
def cargar_paises(request):
if request.is_ajax:
paises = Pais.objects.values('id', 'nombre')
return HttpResponse(json.dumps(paises), mimetype='aplication/json')
you can find the documentation here.
try setting the id's as:
var option = $('<option></option>', {value:(paises[0].aux.id+1), text:desc});

Does Mongoose provide access to previous value of property in pre('save')?

I'd like to compare the new/incoming value of a property with the previous value of that property (what is currently saved in the db) within a pre('save') middleware.
Does Mongoose provide a facility for doing this?
The accepted answer works very nicely. An alternative syntax can also be used, with the setter inline with the Schema definition:
var Person = new mongoose.Schema({
name: {
type: String,
set: function(name) {
this._previousName = this.name;
return name;
}
});
Person.pre('save', function (next) {
var previousName = this._previousName;
if(someCondition) {
...
}
next();
});
Mongoose allows you to configure custom setters in which you do the comparison. pre('save') by itself won't give you what you need, but together:
schema.path('name').set(function (newVal) {
var originalVal = this.name;
if (someThing) {
this._customState = true;
}
});
schema.pre('save', function (next) {
if (this._customState) {
...
}
next();
})
I was looking for a solution to detect changes in any one of multiple fields. Since it looks like you can't create a setter for the full schema, I used a virtual property. I'm only updating records in a few places so this is a fairly efficient solution for that kind of situation:
Person.virtual('previousDoc').get(function() {
return this._previousDoc;
}).set(function(value) {
this._previousDoc = value;
});
Let's say your Person moves and you need to update his address:
const person = await Person.findOne({firstName: "John", lastName: "Doe"});
person.previousDoc = person.toObject(); // create a deep copy of the previous doc
person.address = "123 Stack Road";
person.city = "Overflow";
person.state = "CA";
person.save();
Then in your pre hooks, you would just need to reference properties of _previousDoc such as:
// fallback to empty object in case you don't always want to check the previous state
const previous = this._previousDoc || {};
if (this.address !== previous.address) {
// do something
}
// you could also assign custom properties to _previousDoc that are not in your schema to allow further customization
if (previous.userAddressChange) {
} else if (previous.adminAddressChange) {
}
Honestly, I tried the solutions posted here, but I had to create a function that would store the old values in an array, save the values, and then see the difference.
// Stores all of the old values of the instance into oldValues
const oldValues = {};
for (let key of Object.keys(input)) {
if (self[key] != undefined) {
oldValues[key] = self[key].toString();
}
// Saves the input values to the instance
self[key] = input[key];
}
yield self.save();
for (let key of Object.keys(newValues)) {
if (oldValues[key] != newValues[key]) {
// Do what you need to do
}
}
What I do is use this.constructor within the pre-save route to access the current value in the database.
const oldData = this.constructor.findById(this.id)
You can then grab the specific key you're looking for from the oldData to work with as you see fit :)
let name = oldData.name
Note that this works well for simple data such as strings, but I have found that it does not work well for subschema, as mongoose has built in functionality that runs first. Thus, sometimes your oldData will match your newData for a subschema. This can be resolved by giving it it's own pre-save route!

How do you increment a field in mongodb using c#

Thought this would be pretty straight forward, but my value is remaining the same (0).
What I'd like to do is increment my UnreadMessages field when the user receives a message they haven't read and then decrement it when they have. So I thought code like this would work:
var userHelper = new MongoHelper<User>();
//increment
userHelper.Collection.Update(Query.EQ("Id", userId.ToId()), Update.Inc("UnreadMessages", 1));
//decrement
userHelper.Collection.Update(Query.EQ("Id", userId.ToId()), Update.Inc("UnreadMessages", -1));
After running these no errors are thrown but the value doesn't change either. And no I'm not running one after the other as the code above could be interpreted :)
Update
Here's my helper class:
public class MongoHelper<T> : Sandbox.Services.IMongoHelper<T> where T : class
{
public MongoCollection<T> Collection { get; private set; }
public MongoHelper()
{
var con = new MongoConnectionStringBuilder(ConfigurationManager.ConnectionStrings["MongoDB"].ConnectionString);
var server = MongoServer.Create(con);
var db = server.GetDatabase(con.DatabaseName);
Collection = db.GetCollection<T>(typeof(T).Name.ToLower());
}
}
and thanks to Travis' answer I was able to pull this off:
MongoHelper<UserDocument> userHelper = new MongoHelper<UserDocument>();
var user = userHelper.Collection.FindAndModify(Query.EQ("Username", "a"), SortBy.Null, Update.Inc("MessageCount", 1), true).GetModifiedDocumentAs<UserDocument>();
Not sure what your helper does. Here is a working snippet I use:
var query = Query.And(Query.EQ("_id", keyName));
var sortBy = SortBy.Null;
var update = Update.Inc("KeyValue", adjustmentAmount);
var result = collection.FindAndModify(query, sortBy, update, true);
So, "query" finds the document, update does the increment, and FindAndModify puts them together and actually hits the database.

Using DynamicActivityProperty as OutArgument in ActivityBuilder

Greetings,
I'm trying to create a workflow using a ActivityBuilder, and then get the XAML.
This flow use a custom activity (WaitForInput) to handle bookmarks. This class inherits from NativeActivity.
I'm having a hard time finding a way to set 'Result' property of my WaitForInput activity, which expects a OutArgument.
Creating this same workflow by the VS designer, I could associate the boolean property 'MyResult' InOutArgument called 'wrapper'. Like this : [Wrapper.MyResult]
I would do this by code, and according to my research, I have to use DynamicActivityProperty.
The problem is that I don't know how to use my DynamicActivityProperty as OutArgument in this case.
This is an simplified version of the code:
var wrapper = new DynamicActivityProperty
{
Name = "Wrapper",
Type = typeof(InOutArgument<CommunicationWrapper>),
};
var activityBuilder = new ActivityBuilder();
activityBuilder.Properties.Add(wrapper);
var step1 = new FlowStep
{
//here's my problem
Action = new WaitForInput<bool> { BookmarkName = "step1", Result = ??? }
};
var flow = new Flowchart
{
StartNode = step1,
Nodes = { step1 }
};
I have founded a solution to my own problem
Result = new OutArgument<bool>(new VisualBasicReference<bool>
{ ExpressionText = "Wrapper.MyResult" }); }