I have the following tables:
users:
------
id
first_name
current_property_id
property_users:
---------------
id
user_id
property_id
chat_user_id
nickname
chat_users:
-----------
id
identity
chat_groups:
------------
id
name
type ['Single' means the group a user is having permutation without repetition for all property users that will serve as their 1:1 conversation (in short everyone is paired with everyone once), 'Group' means more than 2 people can be in the group]
last_messaged_at
chat_group_members:
-------------------
id
chat_group_id
user_id
chat_user_id
I need to make a query to fetch all users (except me) in the property I am in and get the chat_groups I have with them (Type == Single).
I tried doing it PHP way but it takes too long (for 125 users it takes +30s of response)
This is how I am doing it in PHP
$this->currentUser = auth()->user();
//this is Fluent using DB::table and joining property_users, chat_users, and users
$propertyUsers = $this->run(GetPropertyUsersJob::class, [
'property' => $this->property
]);
//this is using simple eloquent getting groups
$chatGroups = $this->run(GetGroupsJob::class, [
'property' => $this->property,
'type' => ChatGroup::TYPE_SINGLE
]);
$chatGroups->load('members.user');
//first level of loop
foreach($propertyUsers as $propertyUser) {
if($this->currentUser->id == $propertyUser->user_id) {
return [];
}
$chatGroupId = '';
$chatGroupName = '';
//second level of loop
foreach($chatGroups as $chatGroup) {
$found = 0;
//third level of loop
foreach($chatGroup->members as $member) {
if($member->user_id == $this->currentUser->id) {
$found++;
}
if($member->user_id == $propertyUser->user_id) {
$found++;
}
}
//just to get this, I need to do nested loop 3x
if($found == 2) {
$chatGroupId = $chatGroup->id;
$chatGroupName = $chatGroup->name;
}
}
$user[] = [
'id' => $propertyUser->user_id,
'first_name' => $propertyUser->user->first_name,
'nickname' => $propertyUser->nickname,
'chat_group_id' => $chatGroupId,
'chat_group_name' => $chatGroupName
];
}
How can I convert this to a query (eloquent/fluent) instead?
#Update:
User model: I am only adding related eager loading
-----------
public function property_users()
{
return $this->hasMany(PropertyUser::class, 'user_id', 'id');
}
PropertyUser model:
-------------------
public function user()
{
return $this->belongsTo(User::class);
}
public function chat_user()
{
return $this->hasOne(ChatUser::class, 'id', 'chat_user_id');
}
ChaUser model:
--------------
public function property_user()
{
return $this->belongsTo(PropertyUser::class, 'id', 'chat_user_id');
}
Related
Often I need to validate if given value is existing in certain column (attribute) of a table (model).
This can be useful in foreign keys of a model, to check if the given values exists.
Most probably the validation logic can be mostly the same as for Uniqueness, except the comparison here can be something like > 0.
A possible usage scenario could be like below:
$validator->add(
'organization_id',
new ExistenceOnDbValidator(
[
'model' => Organization::class,
'expr'=> ' id = %s ',
'excludeNullValue'=> true,
'message' => 'Organization does not exist.',
]
)
);
Finally I implemented myself a validator called ExistenceOnDbValidator and it works fine.
Usage
$validator = new Validation();
$validator->add(
'organization_id',
new ExistenceOnDbValidator(
[
'model' => Organization::class,
'expr' => ' id = %s ',
'ignoreNullValue' => false,
'message' => 'Selected organization does not exist.',
]
)
);
Implenentation
use Phalcon\Messages\Message;
use Phalcon\Validation;
use Phalcon\Validation\AbstractValidator;
use Phalcon\Validation\ValidatorInterface;
class ExistenceOnDb extends AbstractValidator implements ValidatorInterface
{
public function validate(Validation $validator, $attribute): bool
{
$expr = $this->getOption('expr');
$model = $this->getOption('model');
$value = $validator->getValue($attribute);
$ignoreNullValue = true;
if ($this->hasOption('ignoreNullValue')) {
$ignoreNullValue = $this->getOption('ignoreNullValue');
}
if ((is_null($value) || empty($value)) && $ignoreNullValue == true) {
return true;
}
$expr = sprintf(
$expr,
$value,
);
$result = $model::findFirst($expr);
if ((is_null($result) || empty($result))) {
$message = $this->getOption('message');
$validator->appendMessage(new Message($message));
return false;
}
return true;
}
}
I have multiselect option in my website.
<select multiple name="genres[]">
<option value="1">action</option>
<option value="2">adult</option>
<option value="3">advanture</option>
<option value="4">anime</option>
<option value="5">biographic</option>
</select>
Also i have fields in db
shows
id name
1 grey's anatomy
2 the morning show
genres
id name
1 action
2 adult
3 advanture
3 anime
5 biographic
data_show_genres
id show_id genre_id
1 1 4
2 1 2
3 2 1
After Submit button, function do
foreach ($input['genres'] as $genre) {
DataShowGenres::updateOrCreate(
['show_id' => $id, 'genre_id' => $genre]
);
}
So adding work's, but when i try to remove, i mean unselect some data. Old still stays. I can always delete old data for that show but is there any way to do this better?
Edit:
Controller:
public function edit_update(Request $request, $id)
{
$request->validate([
'title' => 'required|min:1|max:300',
'imdb' => 'required|min:0|max:10000000|numeric',
'tvdb' => 'required|min:0|max:10000000|numeric',
'youtube' => 'nullable|url',
'hidden' => 'nullable',
]);
$input = $request->all();
$input['hidden'] = $request->has('hidden') ? 1 : 0;
$input['recommend'] = $request->has('recommend') ? 1 : 0;
if (empty($input["genres"])) {
} else {
foreach ($input['genres'] as $genre) {
$zanr = DataShowGenres::updateOrCreate(
['show_id' => $id, 'genre_id' => $genre]
);
}
}
$serija = Serija::FindOrFail($id_serije);
$serija->title = $input['title'];
$serija->imdb = $input['imdb'];
$serija->tvdb = $input['tvdb'];
$serija->imdb_rating = $input['imdb_rating'];
$serija->tmdb = $input['tmdb'];
$serija->hidden = $input['hidden'];
$serija->youtube = $input['youtube'];
$serija->save();
toast('Edited!', 'success');
return back();
}
Route:
Route::get('/serije/izmeni/{id}/{slug}', 'SerijeController#edit')->where(['id' => '[0-9]+', 'title' => '^[a-z0-9]+(?:-[a-z0-9]+)*$'])->middleware('permission:show_edit');
Route::post('/serije/izmeni/{id}/{slug}', 'SerijeController#edit_update')->where(['id' => '[0-9]+', 'naziv' => '^[a-z0-9]+(?:-[a-z0-9]+)*$'])->middleware('permission:show_edit');
Syncing Associations
You may use the sync method to construct many-to-many
associations. The sync method accepts an array of IDs to place on the
intermediate table. Any IDs that are not in the given array will be
removed from the intermediate table. So, after this operation is
complete, only the IDs in the given array will exist in the
intermediate table:
//...
$show = Show::findOrFail($id);
$show->genres()->sync($input['genres']);
//...
I use react native through firebase database
I have a database creating products each product has a number
I want to take a number and compare it with the product number
And if there is then I want to get a product
the function its give me my correct name but where i use it on render its not found the variable (name)
getAllContact = async key => {
let barCodeData2 = this.props.navigation.state.params.barcodeData
let self = this;
let contactRef = firebase.database().ref()
contactRef.on("value", dataSnapsot => {
if (dataSnapsot.val()) {
let contactResult = Object.values(dataSnapsot.val())
let contactKey = Object.keys(dataSnapsot.val())
contactKey.forEach((value, key) => {
contactResult[key]["key"] = value
})
self.setState({
fname: contactResult.fname,
data: contactResult.sort((a, b) => {
var nameA = a.barcode
var nameB = barCodeData2
const name = a.fname
console.log(`${nameA} What numers issssssss`);
if (nameA == nameB) {
alert(`${name} ........`)
console.log(`${nameA == nameB}is Equqlqlqlql`);
return name
}
}),
})
}
})
}
render() {
let t=this.state.name
alert(`${t} how?`)// is give Not found
// let d = this.props.navigation.state.params.barcodeData
return (
)
}
When you try such a comparison query i.e.
let ref = firebase.firestore();
ref.collection('zoo')
.where("id", "==", myID)
.get()
.then((snapshot) => {
console.log(snap.empty); //this will denote if results are empty
snapshot.forEach(snap => {
console.log(snap.exists); //alternatively this will also tell you if it is empty
})
})
well what you can do is run query based on you product no and if there's a product you will a product if there's none you will get an empty array.
read firebase documentation on queries
https://firebase.google.com/docs/reference/js/firebase.database.Query
As shown in the following unit test I expect stats.TotalResults to be 2 but is 3. Why is that?
[Test]
public void RavenQueryStatisticsTotalResultsTest1()
{
using (var db = _documentStore.OpenSession())
{
db.Store(new Club { Name = "Foo1", Type = "Amateur" }); // --> Matches all conditions
db.Store(new Club { Name = "Foo2", Type = "Professional" });
db.Store(new Club { Name = "Foo3", Type = "Amateur" }); // --> Matches all conditions
db.Store(new Club { Name = "Boo1", Type = "Amateur" });
db.Store(new Club { Name = "Boo2", Type = "Professional" });
db.SaveChanges();
}
WaitForIndexing(_documentStore);
using (var db = _documentStore.OpenSession())
{
RavenQueryStatistics stats;
var query = db.Query<Club>()
.Statistics(out stats)
.Where(club => club.Type == "Amateur")
.Intersect()
.Search(club => club.Name, "Foo*", escapeQueryOptions: EscapeQueryOptions.AllowPostfixWildcard);
var clubs = query.ToList();
Assert.AreEqual(2, clubs.Count);
Assert.AreEqual(2, stats.TotalResults); // I expect 2 but was 3! Why is that?
}
}
You need Intersect when using multiple where clauses. To combine Where and Search, you have to pass SearchOptions.And to Search:
using (var db = _documentStore.OpenSession()) {
RavenQueryStatistics stats;
var query = db.Query<Club>()
.Customize(_ => _.WaitForNonStaleResultsAsOfLastWrite())
.Statistics(out stats)
.Where(club => club.Type == "Amateur")
.Search(
club => club.Name,
"Foo*",
escapeQueryOptions: EscapeQueryOptions.AllowPostfixWildcard,
options:SearchOptions.And);
var clubs = query.ToList();
Assert.AreEqual(2, clubs.Count);
Assert.AreEqual(2, stats.TotalResults);
}
I am new to RavenDB. I am trying to use a multi map index feature, though I am not sure if it is the best approach to my problem. So I have three documents: Unit, Car, People.
Car document looks like this:
{
Id: "cars/123",
PersonId: "people/1235",
UnitId: "units/4321",
Make: "Toyota",
Model: "Prius"
}
People document looks like this:
{
Id: "people/1235",
FirstName: "test",
LastName: "test"
}
And unit doc:
{
Id: "units/4321",
Address: "blah blah"
}
This is an abbreviated example, in my real app there are way more fields, so data de-normalization would be my last resort.
I need to create and index that will have all of this three docuemnts joined in one document. Something like this:
{
CarId: "cars/123",
PersonId: "people/1235",
UnitId: "units/4321",
Make: "Toyota",
Model: "Prius"
FirstName: "test",
LastName: "test"
Address: "blah blah"
}
// same unit different person owns a different car
{
CarId: "cars/122",
PersonId: "people/1236",
UnitId: "units/4321",
Make: "Toyota",
Model: "4runner"
FirstName: "test",
LastName: "test"
Address: "blah blah"
}
In a relational database I would just use two joins to People and Unit tables by ids
and my car table would be an aggregate entity.
Here is the index definition that I have:
public class MyMultiIndex : AbstractMultiMapIndexCreationTask<JoinedDocument>
{
public MyMultiIndex()
{
// creating maps
AddMap<Car>(cars => cars.Select(e => new { e.CarId, e.Make, e.Model, PersonId = e.PersonId, UnitId = e.UnitId, FirstName = (null)string, LastName = (null)string, Address = (nul)string }));
AddMap<People>(people => people.Select(e => new { CarId = (string)null, Make = (string)null, Model = (string)null, PersonId = e.Id, UnitId = (null)string, FirstName = e.FirstName, LastName = e.LastName, Address = (nul)string }));
AddMap<Unit>(people => people.Select(e => new { CarId = (string)null, Make = (string)null, Model = (string)null, PersonId = (null)string, UnitId = e.null, FirstName = (nul)string , LastName = (nul)string , Address = e.Address }));
Reduce = results => from result in results
group result by result.CarId
into g
select new JoinedDocument
{
CarId = g.Key,
PersonId = g.First(e => e.CarId == g.Key).PersonId,
UnitId = g.First(e => e.CarId == g.Key).UnitId,
Model = g.First(e => e.CarId == g.Key).Model,
Make = g.First(e => e.CarId == g.Key).Make,
**// this never works. It is like result set does not contain anything with this personId. It looks like AddMap for people document did not work.**
FirstName = results.First(e => e.PersonId == g.First(ie => ie.CarId == g.Key).PersonId).FirstName,
**// this never works. It is like result set does not contain anything with this personId. It looks like AddMap for people document did not work.**
LastName = results.First(e => e.PersonId == g.First(ie => ie.CarId == g.Key).PersonId).LastName,
**// this never works. It is like result set does not contain anything with this personId. It looks like AddMap for unit document did not work.**
UnitAddress = results.First(e => e.UnitId == g.First(ie => ie.CarId == g.Key).UnitId).LastName,
};
Index(map => map.Model, FieldIndexing.Analyzed);
Index(map => map.Make, FieldIndexing.Analyzed);
Index(map => map.LastName, FieldIndexing.Analyzed);
Index(map => map.FirstName, FieldIndexing.Analyzed);
Index(map => map.Make, FieldIndexing.Analyzed);
Index(map => map.UnitAddress, FieldIndexing.Analyzed);
}
}
When RavenDb runs this index I see errors when it is trying to run the Reduce function I have provided. It throws error when I am trying to match a record where person's first name and last name exist, same happens with the unit.
It looks like you're trying to fit a document database with an object model that has relationships. This blog may help you:
Keeping a Domain Model Pure with RavenDB
Keep in mind that this isn't the recommended use of RavenDB, but sometimes it's necessary, and this is a good way to handle it.
Can you have a car with no owner? or an address with no resident? If its false in both cases, I would model the car and unit to be embedded inside a person. So the person becomes your aggregate root and to get to a car or a unit you must go through a person.