how to update document of many to many model - azure-cognitive-search

Need help,
Let's say I have a model of 2 tables with relation of many to many . teachers and students.
I thought to save a document per student. to be able to search by student name but to be able to filter also by the teacher.
so I thought to create the document like that:
{
id: string
studentName: string,
class: string
teachers: [teacherId1: string, teacherId2: string...]
...
}
but what should happens when I remove the teacher from some class, now I need to update all the class student's documents (and I have thousands, how much time it will take (my document itself is not huge)).
Is there an easy way to that? instead of updating a document one by one.
(let's say I have all the list of studentIds)
maybe my document model structure is not correct.
Is there any other good idea.
Thanks,

Related

Avoiding database queries in Anylogic

I would like to avoid costly repeated data base queries in Anylogic. I have seen the following thread in Stack Overflow What is the fastest way to look up continuous data on Anylogic (Java, SQL) where a simple three step answer is provided but I'm not sure what the second point of the three actually means:
Save all rows as instances of that class at model start-up into a map - you can use Origin/Destination as the key (use Anylogic's Pair object) and the class instance as the value
I have created a class that takes as inputs the information from each column of my database. I would now like to save each row as an instance of that class - is there an easy way to do this? I may be missing something simple as I'm new to Anylogic.
I'm also unsure of how to create a mapping, if anyone could add more detail to point 2 above I'd be very grateful!
this is effectively the best advice, you created the class, which is a great step, but now, one element of that class, will be used as the key... for example the name... for instance if your class has firstName as one variable and lastName as another variable, you will use a string that is the concatenation of firstName and lastName as your key. Of course any key is fine, assuming that it is unique for all your table. Also an integer as an id is ok too.
create a collection of type LinkedHashMap
Create a class (you did that)
Your collection will take as the key a String (first + last name) and as the value of the elment the class...
now, when you read your database you will have something like this:
for(Tuple t : yourQueryResults){
YourClass yc=new YourClass(t.get(db.var1),t.get(db.var2));
String totalName=t.get(db.first_name)+"_"+t.get(db.last_name);
yourCollection.put(totalName,yc);
}
Now every time you want to find someone with the a name, for example "John Doe", instead of making a query, you will do
yourCollection.get("John_Doe").theVarYouWant;
if you use an id instead of the name, you can set an int as the key, and then you will just do yourCollection.get(theId).theVarYouWant

How do i search two collection on the same _id

I'm working on a project of mine and I have encountered a problem. Let's suppose that we have three classes (models) respectively Person, Shop, Transaction: the first and second one (Person and shop) are both interacting by creating and pushing in arrays an instance of Transaction. They all look as follows :
Person
{
firstName:String,
lastName:String,
transactions:[ref:Transaction],
...other properties...
}
Shop
{
name:String,
customers:[ref:Person]
transactions:[ref:Transaction],
...other properties...}
}
Transaction
{
from:ref,//id of person||shop
to:ref, //id of person||shop
amount:float
...other properties...
}
Now when some one opens and ask the app for the balance (money they have) he/she should see a list of transaction and the name of the either of the two other class... so normal populate or lookup won't do cause in the two different collection the id's might be the same so one of the way I wanted to address it was by creating an extra id that would be used when creating any of the Person and Shop instance thus any will have its own id (example: person.id-> 1,shop.id->2). But we would do first a query on id in the Person collection and then if this result is null we would then perform the second query on id in the Shop collection... I don't really like this solution so if anyone reading this have a solution please share it with me ... Thanks in advance
Edit: The Person instances may also send transactions to one an other

How do i properly design a data model for Recipe / Ingredient using MongoDB

Recently i have designed a database model or ERD using Hackalode.
So the problem I'm currently facing is that base on my current design, i can't query it correctly as I wanted. I studied ERD with MYSQL and do know that Mongo doesn't work the same
The idea was simple, I want a recipe that has a array list of ingredients, and the ingredients are from separate collection.
The recipe also consist of measurement of the ingredient ie. (1 tbps sugar)
Can also query from list of ingredients and find the recipe that contains the ingredients
I wanted this collections to be in Many to Many relationship and the recipe can use the ingredients that are already in the database.
I just don't know how to query the data
I have tried a lot of ways by using $elemMatch and populate and all i get is empty array list as a result.
Im expecting two types of query where i can query by name of ingredients or by the recipe
My expectation result would be like this
[{
id: ...,
name: ....,
description: ...,
macros: [...],
ingredients: [
{
id,
amount: ....,
unit: ....
ingredient: {
id: ....,
name: ....
}
}
}, { ... }]
But instead of getting
[]
Imho, your design is utterly wrong. You over normalized your data. I would do something much simpler and use embedding. The reasoning behind that is that you define your use cases first and then you model your data to answer the question arising from your use cases in the most efficient way.
Assumed use cases
As a user, I want a list of all recipes.
As a user, I want a list of all recipes by ingredient.
As a designer, I want to be able to show a list of all ingredients.
As a user, I want to be able to link to recipes for compound ingredients, should it be present on the site.
Surely, this is just a small excerpt, but it is sufficient for this example.
How to answer the questions
Ok, the first one is extremely simple:
db.recipes.find()[.limit()[.skip()]]
Now, how could we find by ingredient? Simple answer: do a text index on ingredient names (and probably some other fields, as you can only have one text index per collection. Then, the query is equally simple:
db.recipes.find({$text:{$search:"ingredient name"}})
"Hey, wait a moment! How do I get a list of all ingredients?" Let us assume we want a simple list of ingredients, with a number on how often they are actually used:
db.recipes.aggregate([
// We want all ingredients as single values
{$unwind:"$Ingredients"},
// We want the response to be "Ingredient"
{$project:{_id:0,"Ingredient":"$Ingredients.Name"}
// We count the occurrence of each ingredient
// in the recipes
{$group:{_id:"$Ingredient",count:{$sum:1}}}
])
This would actually be sufficient, unless you have a database of gazillions of recipes. In that case, you might want to have a deep look into incremental map/reduce instead of an aggregation. Hint: You should add a timestamp to the recipes to be able to use incremental map/reduce.
If you have a couple of hundred K to a couple of million recipes, you can also add an $out stage to preaggregate your data.
On measurements
Imho, it makes no sense to have defined measurements. There are teaspoons, tablespoons, metric and imperial measurements, groupings like "dozen" or specifications like "clove". Which you really do not want to convert to each other or even set to a limited number of measurements. How many ounces is a clove of garlic? ;)
Bottom line: Make it a free text field, maybe with some autocomplete suggestions.
Revised data model
Recipe
{
_id: new ObjectId(),
Name: "Surf & Turf Kebap",
Ingredients: [
{
Name: "Flunk Steak",
Measurement: "200 g"
},
{
Name: "Prawns",
Measurement: "300g",
Note: "Fresh ones!"
},
{
Name: "Garlic Oil",
Measurement: "1 Tablespoon",
Link: "/recipes/5c2cc4acd98df737db7c5401"
}
]
}
And the example of the text index:
db.recipes.createIndex({Name:"text","Ingredients.Name":"text"})
The theory behind it
A recipe is you basic data structure, as your application is supposed to store and provide them, potentially based on certain criteria. Ingredients and measurements (to the extend where it makes sense) can easily be derived from the recipes. So why bother to store ingredients and measurements independently. It only makes your data model unnecessarily complicated, while not providing any advantage.
hth

SQL Query to Count Duplicate Values in String

I've searched for an answer to this here on the boards and elsewhere - I'm guessing this issue has already been resolved, but for some reason, I'm not finding what I need... so, I'll ask and hope this isn't a duplicated question.
What I have is a list of students and employees in a MSSQL database. One of the columns contains a string with the current term (semester) with an identifier for each class that the student is registered for, delimited by ';' for each entry.
What I'm trying to figure out is how to return a value of students who are signed up for more than 4 classes for the current semester. To get a count of all students registered for the current semester, the query is simple:
SELECT COUNT(*) AS Current_Students
FROM UserData
WHERE StuTermClassString LIKE '%2163%'
This works fine to return the total number of students, but I need a way to return a value of the full-time students (those that have more than 11 class hours per semester, which is typically 4+ classes). So I need a way to determine when the count of classes with '%2163%' for a record is > 4. If I haven't explained this well enough, please let me know and I'll expand on it more. Thanks!
Unfortunately handling pseudo-arrays packed into a string in SQL happens.
You will need to create a string splitting function to parse out the individual items in the list string and present them as a table variable.
See: http://sqlperformance.com/2012/07/t-sql-queries/split-strings
There are many ways to do this, but you should end up with a table variable that can use the standard built-in set oriented SQL functions to find what you need.
Direct answer to your question:
WHERE StuTermClassString LIKE "%2163%;%;%;%;%"<-- assuming the semester indicator is before the class names, and each class name has a semicolon after it.
But, might I suggest a more reasonable DB structure? Instead of having a column in your Student table with a string of ;-delimited class names, you could have a second table of Registrations, where each row has a Student ID (referring to a row in your Student table), a Semester Number, and a single class name. This way you could query for students with more than a certain number of classes by doing:
SELECT student_id FROM Registrations WHERE semester_number = "2163" GROUP BY student_id HAVING COUNT(student_id) > 3

objectify query filter by list in entity contains search parameter

in an app i have an entity that contains a list of other entities (let's say an event holding a list of assigned employees)
using objectify - i need to find all the events a particular employee is assigned to.
is there a basic way to filter a query if it contains the parameter - kind of the opposite of the query in
... quick pseudocode
findAll(Employee employee) {
...
return ofy.query(Event.class).filter("employees.contains", employee).list();
}
any help would be greatly appreciated
i tried just doing filter("employees", employee) after seeing this http://groups.google.com/group/objectify-appengine/browse_thread/thread/77ba676192c08e20 - but unfortunately this returns me an empty list
currently i'm doing something really inefficient - going through each event, iterating through the employees and adding them to a new list if it contains the given employee just to have something that works - i know this is not right though
let me add one thing,
the above query is not actually what it is, i was just using that because i did not think this would make a difference.
The Employee and Events are in the same entity group with Business as a parent
the actual query i am using is the following
ofy.query(Event.class).ancestor(businessKey).filter("employees", employee).list();
unfortunately this is still returning an empty list - does having the ancestor(key) in there mess up the filter?
solution, the employees field was not indexed correctly.
I added the datastore-indexes file to create a composite index, but was testing originally on a value that I added before the employees field was indexed, this was something stupid i was doing - simply having an index on the "business" field and the "employees" field fixed everything. the datastore-indexes file did not appear to be necessary, after deleting it and trying again everything worked fine.
Generally, you do this one of two ways:
Put a property of Set<Key<Employee>> on the Event
or
Put a property of Set<Key<Event>> on the Employee
You could also create a relationship entity, but if you're just doing filtering on values with relatively low counts, usually it's easier to just put the set property on one entity or the other.
Then filter as you describe:
ofy.query(Event.class).filter("employees", employee).list()
or
ofy.query(Employee.class).filter("events", event).list()
The list property should hold a Keys to the target entity. If you pass in an entity to the filter() method, Objectify will understand that you want to filter by the key instead.
Example :
/***************************************************/
#Entity
#Cache
public class News {
#Id Long id;
String news ;
#Index List<Long> friend_list = new ArrayList<Long>();
// My friends who can see my news , exemele : friend_list.add(id_f1); friend_list.add(id_f2); friend_list.add(id_f3);
//To make an operation on "friend_list", it is obligatory to index it
}
/*************************************************/
public News(Long id_f){
List<Long> friend_id = new ArrayList<Long>();
friend_id.add(id_f);
Query<Nesw> query = ofy().load().type(News.class).filter("friend_list in",friend_id).limit(limit);
//To filter a list, just after the name of the field you want to filter, add "IN".
//here ==> .filter("friend_list in",friend_id);
// if friend_list contains "id_friend" ==> the query return value
.........
}

Resources