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

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.

Related

And Operator in Criteria not working as expected for nested documents inside aggregation Spring Data Mongo

I am trying to fetch total replies where read values for a replies is true. But I am getting count value as 3 but expected value is 2 (since only two read value is true) through Aggregation function available in Spring Data Mongo. Below is the code which I wrote:
Aggregation sumOfRepliesAgg = newAggregation(match(new Criteria().andOperator(Criteria.where("replies.repliedUserId").is(userProfileId),Criteria.where("replies.read").is(true))),
unwind("replies"), group("replies").count().as("repliesCount"),project("repliesCount"));
AggregationResults<Comments> totalRepliesCount = mongoOps.aggregate(sumOfRepliesAgg, "COMMENTS",Comments.class);
return totalRepliesCount.getMappedResults().size();
Using AND Operator inside Criteria Query and passed two criteria condition but not working as expected. Below is the sample data set:
{
"_id" : ObjectId("5c4ca7c94807e220ac5f7ec2"),
"_class" : "com.forum.api.domain.Comments",
"comment_data" : "logged by karthe99",
"totalReplies" : 2,
"replies" : [
{
"_id" : "b33a429f-b201-449b-962b-d589b7979cf0",
"content" : "dasdsa",
"createdDate" : ISODate("2019-01-26T18:33:10.674Z"),
"repliedToUser" : "#karthe99",
"repliedUserId" : "5bbc305950a1051dac1b1c96",
"read" : false
},
{
"_id" : "b886f8da-2643-4eca-9d8a-53f90777f492",
"content" : "dasda",
"createdDate" : ISODate("2019-01-26T18:33:15.461Z"),
"repliedToUser" : "#karthe50",
"repliedUserId" : "5c4bd8914807e208b8a4212b",
"read" : true
},
{
"_id" : "b56hy4rt-2343-8tgr-988a-c4f90598h492",
"content" : "dasda",
"createdDate" : ISODate("2019-01-26T18:33:15.461Z"),
"repliedToUser" : "#karthe50",
"repliedUserId" : "5c4bd8914807e208b8a4212b",
"read" : true
}
],
"last_modified_by" : "karthe99",
"last_modified_date" : ISODate("2019-01-26T18:32:41.394Z")
}
What is the mistake in the query that I wrote?

MongoDb - Query for specific subdocument

I have a set of mongodb documents with the following structure:
{
"_id" : NUUID("58fbb893-dfe9-4f08-a761-5629d889647d"),
"Identifiers" : {
"IdentificationLevel" : 2,
"Identifier" : "extranet\\test#test.com"
},
"Personal" : {
"FirstName" : "Test",
"Surname" : "Test"
},
"Tags" : {
"Entries" : {
"ContactLists" : {
"Values" : {
"0" : {
"Value" : "{292D8695-4936-4865-A413-800960626E6D}",
"DateTime" : ISODate("2015-04-30T09:14:45.549Z")
}
}
}
}
}
}
How can I make a query with the mongo shell which finds all documents with a specific "Value" (e.g.{292D8695-4936-4865-A413-800960626E6D} in the Tag.Entries.ContactLists.Values path?
The structure is unfortunately locked by Sitecore, so it is not an options to use another structure.
As your sample collection structure show Values is object, it contains only one Value. Also you must check for Value as it contains extra paranthesis. If you want to get Value from given structure try following query :
db.collection.find({
"Tags.Entries.ContactLists.Values.0.Value": "{292D8695-4936-4865-A413-800960626E6D}"
})

Error in mongodb query to get movie based on id

> db.movmodels.findOne()
{
"_id" : ObjectId("55320b0e0e9e0d9d0540593c"),
"username" : "punk",
"favMovies" : [
{
"alternate_ids" : {
"imdb" : "0137523"
},
"abridged_cast" : [
{
"characters" : [
"Tyler"
],
"id" : "162652627",
"name" : "Brad Pitt"
},
{
"characters" : [
"Narrator"
],
"id" : "162660884",
"name" : "Edward Norton"
},
{
"characters" : [
"Robert"
],
"id" : "162676383",
"name" : "Meat Loaf"
},
{
"characters" : [
"Angel Face"
],
"id" : "162653925",
"name" : "Jared Leto"
},
{
"characters" : [
"Boss"
],
"id" : "770706064",
"name" : "Zach Grenier"
}
],
"synopsis" : "",
"ratings" : {
"audience_score" : 96,
"audience_rating" : "Upright",
"critics_score" : 80,
"critics_rating" : "Certified Fresh"
},
"release_dates" : {
"dvd" : "2000-06-06",
"theater" : "1999-10-15"
},
"critics_consensus" : "",
"runtime" : 139,
"mpaa_rating" : "R",
"year" : 1999,
"title" : "Fight Club",
**"id" : "13153"**
}
],
"__v" : 0
}
This is my data in mongodb.
As I am new to mongodb I wanted to know query to get movie with a particular id.
The query that I tried is. I need to get the movie based on id so that I can remove it from my database
db.movmodels.findOne({username:"punk"},{favMovies:{id:13153}})
but this gives me error.
2015-04-18T05:41:26.221-0400 E QUERY Error: error: {
"$err" : "Can't canonicalize query: BadValue ported projection option: favMovies: { id: 13153.0 }",
"code" : 17287
}
at Error (<anonymous>)
at DBQuery.next (src/mongo/shell/query.js:259:15)
at DBCollection.findOne (src/mongo/shell/collection.js:188:22)
at (shell):1:14 at src/mongo/shell/query.js:259
There are several problems with your query:
The second parameter to find() is a projection, not part of the query. What you want is to supply one document for the query that has two properties: {"username" : "punk", favMovies : { ... } }
However, you also don't want to compare the entire sub-document favMovies, but you only want to match on one of its properties, the id, which requires to 'reach into the object' using the dot operator: {username:"punk", "favMovies.id" : 13153}.
However, that will probably not work yet, because 13153 is not the same as "13153", the latter being a string while the former is a number in JSON.
db.movmodels.findOne({username:"punk", "favMovies.id" : "13153"})
Keep in mind, however, that this will find the entire document for the user named "punk". I'm not sure what exactly your data structure should look like, but it appears you'll have to $pull the movie from the user. In general, I'd say you're embedding too much data into the user, but that's hard to tell without knowing the exact use case.
Here you go:
If you just wanted to get first user who has this fav movie:
db.movmodels.findOne({"favMovies.id": 13153});
And, if you want to know if that user has that movie as favorite.
db.movmodels.findOne({"favMovies.id": 13153, username:"punk"});
Second argument in the findOne is used to only return particular field.
You can use also $elemMatch projection operator (not to be confused with the $elemMatch query operator)
db.movmodels.find({username:"punk"},{favMovies:{$elemMatch:{id:"13153"}}});
`
If you want to find a movie that has another movie (with id 13153) in 'favMovies' array, then write the query as below:
db.movmodels.findOne({username:"punk",'favMovies.id':13153})
And if you want to find a movie with _id 55320b0e0e9e0d9d0540593cwrite the following query:
db.movmodels.findOne({username:"punk",'_id':ObjectId("55320b0e0e9e0d9d0540593c")})

Get specific object in array of array in MongoDB

I need get a specific object in array of array in MongoDB.
I need get only the task object = [_id = ObjectId("543429a2cb38b1d83c3ff2c2")].
My document (projects):
{
"_id" : ObjectId("543428c2cb38b1d83c3ff2bd"),
"name" : "new project",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b"),
"members" : [
ObjectId("5424ac37eb0ea85d4c921f8b")
],
"US" : [
{
"_id" : ObjectId("5434297fcb38b1d83c3ff2c0"),
"name" : "Test Story",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b"),
"tasks" : [
{
"_id" : ObjectId("54342987cb38b1d83c3ff2c1"),
"name" : "teste3",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b")
},
{
"_id" : ObjectId("543429a2cb38b1d83c3ff2c2"),
"name" : "jklasdfa_XXX",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b")
}
]
}
]
}
Result expected:
{
"_id" : ObjectId("543429a2cb38b1d83c3ff2c2"),
"name" : "jklasdfa_XXX",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b")
}
But i not getting it.
I still testing with no success:
db.projects.find({
"US.tasks._id" : ObjectId("543429a2cb38b1d83c3ff2c2")
}, { "US.tasks.$" : 1 })
I tryed with $elemMatch too, but return nothing.
db.projects.find({
"US" : {
"tasks" : {
$elemMatch : {
"_id" : ObjectId("543429a2cb38b1d83c3ff2c2")
}
}
}
})
Can i get ONLY my result expected using find()? If not, what and how use?
Thanks!
You will need an aggregation for that:
db.projects.aggregate([{$unwind:"$US"},
{$unwind:"$US.tasks"},
{$match:{"US.tasks._id":ObjectId("543429a2cb38b1d83c3ff2c2")}},
{$project:{_id:0,"task":"$US.tasks"}}])
should return
{ task : {
"_id" : ObjectId("543429a2cb38b1d83c3ff2c2"),
"name" : "jklasdfa_XXX",
"author" : ObjectId("5424ac37eb0ea85d4c921f8b")
}
Explanation:
$unwind creates a new (virtual) document for each array element
$match is the query part of your find
$project is similar as to project part in find i.e. it specifies the fields you want to get in the results
You might want to add a second $match before the $unwind if you know the document you are searching (look at performance metrics).
Edit: added a second $unwind since US is an array.
Don't know what you are doing (so realy can't tell and just sugesting) but you might want to examine if your schema (and mongodb) is ideal for your task because the document looks just like denormalized relational data probably a relational database would be better for you.

In MongoDB, how to filter by location, sort by another field and paginate the results correctly?

When i don't use pagination, everything works fine (i have only 3 records in this collection, so all of them are listed here):
db.suppliers.find({location: {$near: [-23.5968323, -46.6782386]}},{name:1,badge:1}).sort({badge:-1})
{ "_id" : ObjectId("4f33ff549112b9b84f000070"), "badge" : 3, "name" : "Dedetizadora Alvorada" }
{ "_id" : ObjectId("4f33ff019112b9b84f00005b"), "badge" : 2, "name" : "Sampex Desentupidora e Dedetizadora" }
{ "_id" : ObjectId("4f33feae9112b9b84f000046"), "badge" : 1, "name" : "Higitec Desentupimento e Dedetização" }
But when i try to paginate from the first to the second page, one record doesn't show up and one is repeated:
db.suppliers.find({location: {$near: [-23.5968323, -46.6782386]}},{name:1,badge:1}).sort({badge:-1}).skip(0).limit(2)
{ "_id" : ObjectId("4f33ff549112b9b84f000070"), "badge" : 3, "name" : "Dedetizadora Alvorada" }
{ "_id" : ObjectId("4f33feae9112b9b84f000046"), "badge" : 1, "name" : "Higitec Desentupimento e Dedetização" }
db.suppliers.find({location: {$near: [-23.5968323, -46.6782386]}},{name:1,badge:1}).sort({badge:-1}).skip(2).limit(2)
{ "_id" : ObjectId("4f33feae9112b9b84f000046"), "badge" : 1, "name" : "Higitec Desentupimento e Dedetização" }
Am i doing something wrong or is this some kind of bug?
edit:
Here is a workaround for this. Basically you shouldn't mix $near queries with sorting; use $within instead.
There is an open issue regarding the same problem. Please have a look & vote Geospatial result paging fails when sorting with additional keys