mongoid 'exists' don't work as expected - ruby-on-rails-3

Hi am trying out a query and is giving me strange results. I am trying to get a list of object where a field doesn't exist with a where clause added to it.
Step one the where clause:
ContentMirror.where(source: 'some_source').count
This query returns 9984 records.
some_source have a field call vid_emded_obj which I know some are nil For example:
ContentMirror.find('50fff286781200986e000ae3')
=> #<ContentMirror _id: 50fff286781200986e000ae3, _type: nil, created_at: 2012-12-15 13:12:22 UTC, updated_at: 2013-01-29 12:10:23 UTC, deleted_at: nil, title: "Introduction to Polynomials", vid_emded_obj: nil, media_type: "video", source: "some_source", thumbnail_url: nil, md5: "459173975a7fb145b3ca8b99e1c2ae78">
So I was expecting that at lest that count of 1 will return if I do this:
ContentMirror.where(source: 'some_source').exists(vid_emded_obj: false).count
=> 0
Cannot work out why...

I belkieve that exists checks if the property is there at all, and will return true if the value of that property is empty.
I will just go hunt for the doc to confirm :)
EDIT:
So, the doc does not mention any exists(...).
Only an exists? method that can be applied on a criteria.
I think you should do (pseudo code, I haven't tried it)
ContentMirror.count(vid_embed_obj:nil, source: 'some_source')
or
ContentMirror.where(vid_embed_obj:nil, source: 'some_source').count
or again
ContentMirror.excludes(vid_embed_obj:nil).where(source: 'some_source').count

Related

Pymongo using hint on find_one gets AttributeError

Im need to preform a mongodb find_one query with pymongo but get AttributeError: 'NoneType' object has no attribute 'hint' since there are no results matching the filter
db.collection_name.find_one( filter=filter_query, projection={ _id: False, date: True, }, sort=[ ( date, pymongo.DESCENDING, ) ], ).hint('some_index')
also tried
db.collection_name.find_one( filter=filter_query, projection={ _id: False, date: True, }, sort=[ ( date, pymongo.DESCENDING, ) ], hint='some_index'
)
I know I can do it with find() but is there a way to do it with find_one?
The first approach definitely won't work. The second requires the hint parameter to be passed in the same format used to create the index, e.g. [('field', ASCENDING)].
https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html#pymongo.collection.Collection.find

Creating an index for all active items

I have a collection of documents that follow this schema {label: String, status: Number}.
I want to introduce a new field, deleted_at: Date that will hold information if a document has already been deleted. Seems like a perfect use case for an index, to be able to search for all undeleted tasks.
CreateIndex({
name: "activeTasks",
source: Collection("tasks"),
terms: [
{ field: ["data", "deleted_at"] }
]
})
And then filter by undefined / null value in shell:
Paginate(Match(Index("activeTasks"), null))
Paginate(Match(Index("activeTasks"), undefined))
It returns nothing, even for documents where I explicitly set deleted_at to null.
That's not my point, though. I want to get documents that do not have the deleted_at defined at all, so that I do not have to update the whole collection.
PS. When I add document where deleted: "test" and query for it, the shell does return the expected result.
What do I don't get?
The reason is because FaunaDB doesn't support reading empty/null value the way you think it does. You need to use a special Bindings to do that.
Make sure to check out https://docs.fauna.com/fauna/current/tutorials/indexes/bindings.html#empty for a more thorough explanation and examples.
My understanding of how bindings work would yield the following code. I haven't tested it though and I'm not sure it works.
You need a special binding index:
CreateIndex({
name: "activeTasks",
source: [{
collection: Collection("tasks"),
fields: {
null_deleted_at: Query(
Lambda(
"doc",
Equals(Select(["data", "deleted_at"], Var("doc"), null), null)
)
)
}
}],
terms: [ {binding: "null_deleted_at"} ],
})
Usage:
Map(
Paginate(Match(Index("activeTasks"), true)),
Lambda("X", Get(Var("X")))
)

Find object with value in its array

I'm using lokijs, which has "mongo-similar" query language.
devices.insert({key:'d1', name:'Device1', users:['u1'], status: 'OK', current_wl:'123'})
devices.insert({key:'d2', name:'Device2', users:['u1','u1'], status: 'OK', current_wl:'123'})
devices.insert({key:'d3', name:'Device3', users:['u2','u3'], status: 'OK', current_wl:'123'})
devices.insert({key:'d4', name:'Device4', users:['u1','u2','u3','u4'], status: 'OK', current_wl:'123'})
My attempt to find a device having user 'u1' in its array users returns emty list:
a= devices.find( {users:{ "$in" : ["u1"] }} )
console.log("A", a);
Is the query correct, if the problem was for mongodb?
Is there another way to do it in mongo?
Is there another way to do it in lokijs?
I'm not sure about lokijs, but that's the correct query in Mongo.
If you're only ever going to query for documents that contain a single specific item in their "users" array, a simpler query for this case in Mongo would be:
db.collection.find({ users: "u1" })
I found a solution (or a work-around) using where:
a= devices.where( function(obj){
return obj.users.indexOf('u1') > -1;
}
);

MuleSoft DataWeave check if XML fild exists or not

I have the following mule DataWeave transformation:
([]) when (payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments =="") otherwise
{
Id: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.#id as :string,
Date: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Date,
Time: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Time,
Cancel: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Cancel as :string,
VisitType: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#VisitType,
VisitTypeID: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#VisitTypeID as :string,
Duration: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Duration as :string,
Confirm: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Confirm as :string,
Providers: {
Provider: {
Id: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Providers.ns0#Provider.#id as :string,
Name: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Providers.ns0#Provider.#name,
Department: {
Id: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Providers.ns0#Provider.ns0#Department.#id as :string,
Name: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Providers.ns0#Provider.ns0#Department.#name,
Center: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Providers.ns0#Provider.ns0#Department.#center,
DepartmentDirections: "" when payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Providers.ns0#Provider.ns0#Department.ns0#DepartmentDirections == null otherwise payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Providers.ns0#Provider.ns0#Department.ns0#DepartmentDirections
}
}
},
PatientInstructions: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#PatientInstructions,
Copay: payload.ns0#GetFutureAppointmentsResponse.ns0#Appointments.ns0#Appointment.ns0#Copay as :string
}
Everything works except that the field "DepartmentDirections" doesn't always get passed in the XML. So now when i add this field my webservice doesn't return anything but when i remove it works. Since the field may or may not be there i don't think checking for null is going to help (in the scenario that it is not working the field is not there). Is there a way to easily check if the actual field exists (not the value) before assigning it?
Add header skipNullOn="everywhere", it will skip the fields when transforming if not present in input.
%output application/json skipNullOn="everywhere"
Works only for XML and JSON
For reference: https://docs.mulesoft.com/mule-user-guide/v/3.7/dataweave-reference-documentation

map(&:id) work but not pluck(:id)

In part of my code I need to grab users's id but pluck doesn't grab them. Only map(&:id) can do it. I was wondering why.
I've wrote a quick and dirty block of code to find what's happen
def remove_users user_ids
p users_to_remove.class
users_to_remove = self.users.where(id: user_ids)
if users_to_remove.present?
self.users -= users_to_remove
self.save
p users_to_remove.class
p users_to_remove
Rails::logger.info "\n#{users_to_remove}\n"
users_to_remove_map = users_to_remove.map(&:id)
p users_to_remove_map
Rails::logger.info "\nmap id: #{users_to_remove_map}\n"
users_to_remove_pluck = users_to_remove.pluck(:id)
p users_to_remove_pluck
Rails::logger.info "\npluck id: #{users_to_remove_pluck}\n"
#...
end
self.user_ids
end
Who return in my test.log
#<User::ActiveRecord_AssociationRelation:0x007fb0f9c64da8>
map id: [144004]
(0.3ms) SELECT "users"."id" FROM "users" INNER JOIN "groups_users" ON "users"."id" = "groups_users"."user_id" WHERE "groups_users"."group_id" = $1 AND "users"."id" IN (144004, 144005) [["group_id", 235819]]
pluck id: []
And in my test
User::ActiveRecord_AssociationRelation
User::ActiveRecord_AssociationRelation
#<ActiveRecord::AssociationRelation [#<User id: 144004, created_at: "2015-08-06 08:55:11", updated_at: "2015-08-06 08:55:11", email: "user_2#test.com", token: "rpf5fqf5bs1ofme6aq66fwtcz", reset_password_token: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, disabled: false, first_name: "John_2", last_name: "Rivers_4", is_owner: false, organisation_id: 235826, encrypted_password: "$2a$04$8ev1j...f6ICL.ezS....", reset_password_sent_at: nil, default_language: nil, uid: nil, api_key: "rmhh...noyn">]>
[144004]
[]
The strange thing is. I have user with id. map can get them. pluck not.
I don't understand sql log also. How can I get map id result without any select in sql log? Caching ?
pluck doesnt work on an array, it works on an ActiveRecord::Relation, it's goal is to avoid to make a full query to only get the ids.
Once you've retrieved all columns from db, you can just map what you need.
You create the array when you do self.users -= users_to_remove, or maybe even when you do .present?, since you should use .exists?
This line:
users_to_remove = self.users.where(id: user_ids)
Doesn't fire off SQL query immediately. It sends the request whenever you need some details of these users. And it caches the result in SQL cache (so when the same request goes to DB again, it intercepted by Rails and never reaches the database).
So when you call:
users_to_remove.map(&:id)
It uses that cached result. But when you use
users_to_remove.pluck(:id)
It re-fetches the result, because the actual SQL query differs. With #map it is SELECT * FROM ..., and with #pluck it's SELECT id FROM.... And when query reaches the database, IDs doesn't belong to 'self' any longer (you deleted them right before that), so they aren't returned.