Get all objects where a property matches a value nested in array - mongodb

I have the following data table:
{
"_id" : ObjectId("value"),
"owner" : "testuser",
"date" : ISODate("2017-03-16T12:45:03.386Z"),
"location" : "thuis",
"venue" : "bijna thuis",
"description" : "fghgfh",
"completed" : false,
"winnerName" : null,
"subscriptions" : [],
"interactions" : [
{
"_id" : ObjectId("objectid"),
"owner" : "testuser",
"type" : "guess",
"date" : ISODate("2017-03-06T12:13:10.049Z"),
"answer" : false,
"message" : "test 1"
},
{
"_id" : ObjectId("objectid"),
"owner" : "testuser",
"type" : "guess",
"date" : ISODate("2017-03-06T12:13:10.049Z"),
"answer" : false,
"message" : "test 2"
}
],
"__v" : 0,
"active" : true
}
The above is just one game object. Which means we got several of this objects in our database.
I am trying to get only the interactions where the owner == "testuser".
The problem is that I cannot seem to figure out the best way to do this.
In my code I got 2 objects ( Game & Interaction) where Game has an array of interactions.
Is there someway I can still do this using the mongocsharpdriver.
Thanks in advance for all the help.

Hope it work for you Thanks :-)
collection.Find(x => x.owner == "testuser").ToList(); //where collection is MongoDB collection

Thanks for all the suggestions and sorry for the late response. But I find a way to solve it like this:
var filter = Builders<Game>.Filter.ElemMatch("interactions",
Builders<Interaction>.Filter.Eq("owner", owner));
var interactions = await MongoCollection.Find(filter).ToListAsync();
return interactions.SelectMany(item => item.Interactions).ToList();
This will it will return all the interactions that has a certain user as owner.
Hope I can help somebody out with this answer.

Related

Migrating data in MongoDB

I am working on an application and I need to move the Stripe payment data I have saved around in my user model. I am looking for the best way of doing this. My current data is stored at user.stripe.<value> but I want to move it to user.company.stripe.<value>
Is there tools out there that can handle moving this data around for me or will I need to create a tool to handle this myself? I will be doing a decent amount of this type of data movement during a major refactor (more like a rewrite) so making a tool if non exists is okay with me just no idea how to migrate the data and other Stack Overflow posts are not being of much use that I have found.
Probably picked a bad day/time to post too... Hopefully someone can help me out with examples or direction on where to go from here.
What I want the data to look like:
{ "_id" : ObjectId("5b89c571d855a23b5b07fe95"), "company" : { "customForms" : [ ], "subUserCount" : 1, "stripe" : { "plan" : "<plan Name>", "customerId" : "cus_<ID>", "last4" : "4242", "subscriptionId" : "sub<ID>", "isCoupon" : false } }, "email" : "john.doe#example.ca", "password" : "$2a$10$gMbdy5Dh9Ym..xbVAvhaJO2xhVARAL3oXvad/fX4zAcCuZB88tR1C", "role" : "company", "companyID" : "da89bdee-4123-444c-b221-d41212320a90", }
Current data format:
{ "_id" : ObjectId("5b89c571d855a23b5b07fe95"), "company" : { "customForms" : [ ], "subUserCount" : 1 }, "stripe" : { "plan" : "testplan2", "customerId" : "cus_<ID>", "last4" : "4242", "subscriptionId" : "sub_<ID>", "isCoupon" : false }, "isVerified" : true, "email" : "john.doe#example.ca", "password" : "$2a$10$gMbdy5Dh9Ym..xbVAvhaJO2xhVARAL3oXvad/fX4zAcCuZB88tR1C", "role" : "company", "companyID" : "da89bdee-4123-444c-b221-d41212320a90" }

Getting data range from firebase with swift

I would like to ask that question. The question is how to get specific data range from firebase ?
I have table on firebase like this:
"users" : {
"Jz3IpatRWiWoDbiYM62q6qbHB503" : {
"email" : "Kaanozdemir#gmail.com",
"lastName" : "Ozdemir",
"name" : "Kaan"
},
"PmeYYFiac0c55fU2sFpnTP308mC3" : {
"email" : "kevinhart#gmail.com",
"lastName" : "Hart",
"name" : "Kevin"
},
"r0bMqSGCWihFi2EF4u6ckSzLP8v1" : {
"email" : "Marcusalvarez#gmail.com",
"lastName" : "Alvarez",
"name" : "Marcus"
},
"A3tmSSGCWihFi2EF4u6ckSzLP8c1" : {
"email" : "taylorswift#gmail.com",
"lastName" : "Swift",
"name" : "Taylor"
},
"3SUTsiGCWihFi2EF4u6ckSzLP8v2" : {
"email" : "jimmyfellon#gmail.com",
"lastName" : "Fellon",
"name" : "Jimmy"
},
"lgSit3GCWihFi2EF4u6ckSzLP8u3" : {
"email" : "jaxteller#gmail.com",
"lastName" : "Teller",
"name" : "Jax"
}
For example, I would like to get users values between 2 and 4 [2 - 4](Marcus Alvarez - Taylor Swift - Jimmy Fellon).
Is there any way to do that server side ? I don't wanna get all data and pick values that I want. Anyone knows?
Change your JSON DB structure to include an index in every node :
"users" : {
"autoID1" : {
"email" :.....,
"lastName" : ......,
"name" :.......,
"index" : //e.g.. 1,2,3,4......
}
},
"noOfUsers" : 223,
If you are appending this users node via app, you have too keep track of the no of users in Database node users and keep updating the noOfUsers whenever a new user is added. And to set the next ones index number , just retrieve that node value i.e 223 and sees it and then increment the noOfUsers......
To retrieve between 2-4 .. Now you can use :
Database.database().reference().child("users").queryOrdered(byChild: "index").queryStarting(atValue: "2").queryEnding(atValue: "4").observe....

Mongoid query embedded document and return parent

I have this document, each is a tool:
{
"_id" : ObjectId("54da43aea96ddcc40915a457"),
"checked_in" : false,
"barcode" : "PXJ-234234",
"calibrations" : [
{
"_id" : ObjectId("54da46ec546173129d810100"),
"cal_date" : null,
"cal_date_due" : ISODate("2014-08-06T00:00:00.000+0000"),
"time_in" : ISODate("2015-02-10T17:46:20.250+0000"),
"time_out" : ISODate("2015-02-10T17:46:20.250+0000"),
"updated_at" : ISODate("2015-02-10T17:59:08.796+0000"),
"created_at" : ISODate("2015-02-10T17:59:08.796+0000")
},
{
"_id" : ObjectId("5509e815686d610b70010000"),
"cal_date_due" : ISODate("2015-03-18T21:03:17.959+0000"),
"time_in" : ISODate("2015-03-18T21:03:17.959+0000"),
"time_out" : ISODate("2015-03-18T21:03:17.959+0000"),
"cal_date" : ISODate("2015-03-18T21:03:17.959+0000"),
"updated_at" : ISODate("2015-03-18T21:03:17.961+0000"),
"created_at" : ISODate("2015-03-18T21:03:17.961+0000")
},
{
"_id" : ObjectId("5509e837686d610b70020000"),
"cal_date_due" : ISODate("2015-03-18T21:03:51.189+0000"),
"time_in" : ISODate("2015-03-18T21:03:51.189+0000"),
"time_out" : ISODate("2015-03-18T21:03:51.189+0000"),
"cal_date" : ISODate("2015-03-18T21:03:51.189+0000"),
"updated_at" : ISODate("2015-03-18T21:03:51.191+0000"),
"created_at" : ISODate("2015-03-18T21:03:51.191+0000")
}
],
"group" : "Engine",
"location" : "Here or there",
"model" : "ZX101C",
"serial" : NumberInt(15449),
"tool" : "octane analyzer",
"updated_at" : ISODate("2015-09-30T20:43:55.652+0000"),
"description" : "Description...",
}
Tools are calibrated periodically. What I want to do is grab tools that are due this month.
Currently, my query is this:
scope :upcoming, -> { where(:at_ats => false).where('calibrations.0.cal_date_due' => {'$gte' => Time.now-1.day, '$lte' => Time.now+30.days}).order_by(:'calibrations.cal_date_due'.asc) }
However, this query gets the tool by the first calibration object and it needs to be the last. I've tried a myriad of things, but I'm stuck here.
How can I make sure I'm querying the most recent calibration document, not the first (which would be the oldest and therefore not relevant)?
You should look into aggregation framework and $unwind operator.
This link may be of help.
This link may be helpful. It contains an example of use of 'aggregation framework' for get the last element of the array, that is, the most recent in your case.

$set an embedded value in collection?

I have a document like so:
{
"_id" : "243kAaNRsEvhrguNs",
"createdAt" : ISODate("2015-04-07T16:43:15.299Z"),
"profile" : {
"balance" : 9.71,
"deposited" : 0,
"withdrawn" : 30,
"virgin" : false,
"won" : 29.709999999999997,
"taxable" : false
}
}
and I want to add a field in "profile" called (say) "test". I've tried:
db.users.find({"_id": "243kAaNRsEvhrguNs"},{$set: {"profile.test": "false"}})
but this doesn't seem to work. Can someone help?
EDIT:
Figured it out, was really stupid. This works:
db.users.update({"_id": "243kAaNRsEvhrguNs"},{$set: {"profile.test": "false"}}

MongoDB .Net driver 2.0 Builders Filter (field to array comparison)

I need to get all usernames from "followingList.username" and compare with
posts' usernames, if there any match need to add that one to an array.
Person Model
{
"_id" : ObjectId("554f20f5c90d3c7ed42303e1"),
"username" : "fatihyildizhan",
"followingList" : [
{
"_id" : ObjectId("55505b6ca515860cbcf7901d"),
"username" : "gumusluk",
"avatar" : "avatar.png"
},
{
"_id" : ObjectId("58505b6ca515860cbcf7901d"),
"username" : "yalikavak",
"avatar" : "avatar.png"
},
{
"_id" : ObjectId("58305b6ca515860cbcf7901d"),
"username" : "gumbet",
"avatar" : "avatar.png"
}
]
}
Post Model
{
"_id" : ObjectId("554f2df2a388R4b425b89833"),
"username" : "yalikavak",
"category" : "Summer",
"text" : "blue voyage with yacht"
},
{
"_id" : ObjectId("554f2df2a388P4b425b89833"),
"username" : "yalikavak",
"category" : "Winter",
"text" : "is coming ..."
},
{
"_id" : ObjectId("554f2df2a388K4b425b89833"),
"username" : "gumbet",
"category" : "Fall",
"text" : "there are many trees"
}
I try to get result code block as below but couldn't figure it out.
var filter = Builders<Post>.Filter.AnyEq("username", usernameList);
var result = collection.Find(filter).ToListAsync().Result;
Can you help me with this?
Thanks.
The logic is flipped, what you need is an $in query if I understand your use case correctly:
var filter = Builders<Post>.Filter.In("username", usernameList);
var result = collection.Find(filter).ToListAsync().Result;
In your case, username is a simple field and you want to match against a list of candidates. AnyEq is used to check that, from an embedded list of complex objects, at least one matches a criterion. That still translates to a simple query in MongoDB, but requires to 'reach into' the object which needs a more complicated syntax.