Mongoengine query based on reference field attribute - mongodb

I have the following Documents
Food(Document)
title = fields.StringField()
type = fields.StringField()
Recipe(Document)
title = fields.StringField()
food = fields.ReferenceField(Food)
I would like to get the list of recipes whose food.type == "nonveg"
Can I do something like the following?
Recipe.objects.where(food__type="nonveg")
Thanks!

This is impossible with a single query, as Reference Field hold only the id of the actual document.
Hence, you need to do, two queries,
Which gets all the objects of Food, that fall under your type. This can be done via the code foods = Food.objects(type='nonveg')
Now, use the foods Objects List to filter the Recipe collection as : Recipe.objects(food__in=foods). Also, keep in mind that the in operation takes a list, so always pass a list into the filter query, even if you are getting a single instance in Step 1 using .get()
Wrapping up the steps:
foods = Food.objects(type="nonveg")
recipes = Recipe.objects(food__in=foods)

"type" is a reserved word in mongodb for an operator. So you should use this query : Recipe.objects(food__type__="nonveg")

Recipe.objects(food__type="nonveg") if you use mongoengine.

Related

Do a research in a Firestore document

In my collection "users", each user is defined by their name, list of hobbies, and skills:
Structure of a document in "users":
name : "Name"
hobbies: ["hobby1","hobby2","hobby3"]
skills: ["skill1","skill2","skill3"]
What I want is: Get all documents in the collection where one of those fields contains a specific word. The problem is that currently I get all documents and then I do a loop to retain the matching documents. But I would prefer to do a query instead (reads are expensive). So I was thinking to reorganize the document like this:
New structure:
data: ["Name","hobby1","hobby2","hobby3",skill1","skill2","skill3"]
So I could do a query with "where" and "array-contains". What do you think? Isn't it strange?
If you want to have a OR statement between the hobbies and skills then you can't use a query that uses array-contains. As stated on this documentation:
You can use at most one array-contains clause per query. You can't combine array-contains with array-contains-any.
What I would suggest is to combine the skills and hobbies into one.:
e.g.:
name : "Name"
skillsandhobbies : ["Hobby1", "Hobby2", "Hobby3", "Skill1", "Skill2", "Skill3"]
Then you can use this sample query to get all the documents that have hobbies or skills that contain a specific word:
const q = query(collection(db, "users"), where("skillsandhobbies", "array-contains", "specific-word"));
As I understood from your comments, you basically need to perform a successive search. You need to search the hobbies array for a particular word, and if you don't get any results, you need to perform another search, in the skills array, for the exact same word, and if again you don't get any results, you need to search for the name.
Since you didn't specify a particular programming language, I assume you're using Flutter, as in the other questions of yours. So I will try to explain real quickly how to do it.
First, you need to create the following query:
final queryHobbiesByWord = users.where("hobbies", arrayContains: "word");
Then you have to call get(). As soon as you get a successful callback, you have to check if the number of documents that exist inside the QuerySnapshot is greater than zero. If it is, then perform the logic you want, otherwise, inside the callback create another query that looks like this:
final querySkillsByWord = users.where("skills", arrayContains: "word");
Do the exact same thing as about. If the number of documents that exist inside the QuerySnapshot is greater than zero, then perform the logic you want, otherwise, inside the callback create another query that looks like this:
final queryNameByWord = users.where("name", isEqualTo: "word");
Again, perform the same operation as above, and that's pretty much it. Don't forget to perform each operation inside the callback of the previous one.

I need to get a specific document, where a document contains exactly two specific values

.collection('chats')
.where('members',
arrayContains: List.of([user1,user2]))
.snapshots();
I need to get a specific document, where 'members' contains exactly 'user1' and 'user2' only, and not just one of the values.
Also very important that the order of the values inside the 'members' array/list should be irrelevant..
Because this method using arrayContains is giving me any document that contains either one of these users.
What you're trying to do isn't possible exactly as you've specified. But you can do this if you assume the order of the elements in the array. For that, use a normal isEqualTo filter, providing the exact contents of the array to match. I don't write dart, but it should go something like this:
.where('members', isEqualTo: List.of([user1,user2]))
You can make sure the array always has a consistent order by sorting the items in the array before writing the field, and sorting the array you use in the query.
If the original order of the array is important, then maintain a duplicate field with the same array elements that are always sorted, and query that field instead of the original field.
See also:
FireStore query how to query arrays from the database

Find all objects in database where 5th level value equals specific criteria

I have objects such as this in Mongo database:
{{{}{}}{}}{}{{}{{{}}}
I am not sure how would a query look like to find all objects that match next criteria:
Find all objects where messages[i].payload.headers.name[7].value == aa#aa.com
It appears it is not necessary to use indexes for arrays. The query object I was looking for looks like this:
{"messages.payload.headers.value":"foo#example.com"}

How can I sort query result of play morphia with multi field?

I want to query item from mongoDB using morphia, but I found the order method has only one parameter, can I query data with multi order field like:
List items = Item.q().order("-updateTime").order("-createTime");
You just separate the fields with commas. The wiki has examples: https://github.com/mongodb/morphia/wiki/Query#sort
You can use
List items = Item.q().order("-updateTime,createTime,otherField").asList();

Search and return result in array

I have a collection, like so:
post = {"topics":["japan","japanese","england","chinese"]}
post = {"topics":["canada","japan"]}
post = {"topics":["usa"]}
Now I want to implement a query can return a list of elements by checking the "topics" field to see if it contains a certain character.
For example, query for "ja", it returns all the tags start with "ja":
["japan", "japanese"],
query for "c", returns ["chinese","canada"]
You can not resolve this problem with a single query. You have to maintain either a global list or collection of all tags in order to search them efficiently using regular expressions or you need to iterate over all documents for matching the tags individually for each document.