I'm working on a POC with cf-2021 and mongodb (atl...
# cfml-general
s
I'm working on a POC with cf-2021 and mongodb (atlas). Is there a best practice for handling find() and findOne() results? I was working with findOne(), and if it finds a hit, then all is good, findOne() returns the document. But then I intentionally wanted to see what happens when a match is not found, and the behaviour seems strange:
Copy code
var findResponse = this.findOne( query={ "_id": "mid:#mid#[invalidkey]" } );
		application.utilities.debug( module="daoI4goV5.getMerchant", text="Find #mid#", data=findResponse );
The debug line threw an exception because findResponse did not exist. Is this intentional and is there a best practice for handling this, meaning "try/catch", "isdefined()", "isnull()" (I'm not sure if the last even works, just throwing it out there)?
m
@dfgrumpy any ideas here my friend? I know you've got some experience in the nosql space & CF.
s
isDefined() or isNull() seem the most logical, but I have it engrained in my psyche that isDefined() is bad due to it being extremely inefficient.
d
This is not a unique issue with mongoDB. It is more how to handle referencing non-existent variables. There are a few things you can do. But for me, I would probably set a blank var to expected type first. Then later check to see if it is empty. So…
var findResponse = [];
// do something
arrayIsEmpty(findResponse);
There are a bunch of ways to handle this. This example is just one.
s
Interesting. But won't findResponse be unassigned from the assignment? I see your code working with a try/catch/ignore wrapper and the assignment throwing an exception, but in this case no exception is thrown. I'll give it a try...
d
you could add isArray() && ! arrayIsEmpty() together to make sure it is and has content.
The var will exist because you are setting it to a blank array to start with. findOne won’t make the var not exist if it returns nothing.
s
I tried various versions of the following without joy:
Copy code
var findResponse = {};
		findResponse = this.findOne( query={ "_id": "mid:#mid#x" }, projection=projection );
		application.utilities.debug( module="daoI4goV5.getMerchant", text="Find #mid#", data=isArray(findResponse)?findResponse:{} );
It keeps complaining that findResponse does not exist. Now I did find that isDefined("findReponse") does work, but the psyche thing.
This brings up a dilemma. If I want the following to be as efficient as possible, and not call isDefined() twice, how would I do it:
Copy code
var findResponse = this.findOne( query={ "_id": "mid:#mid#x" }, projection=projection );
		application.utilities.debug( module="daoI4goV5.getMerchant", text="Find #mid#", data=isDefined("findResponse")?findResponse:{} );
		return isDefined("findResponse")?findResponse:{};
If I insert an assignment on line 2:
Copy code
findResponse = isDefined("findResponse")?findResponse:{};
And then simply reference findResponse, does the var scoping still apply, since it was reassigned to non existent?
d
This should do the trick… .
Copy code
var findResponse = {};
        findResponse = this.findOne( query={ "_id": "mid:#mid#x" }, projection=projection );

        result = structKeyExists(variables, 'findResponse') ? variables.findResponse : {};

        application.utilities.debug( module="daoI4goV5.getMerchant", text="Find #mid#", data=result );
		return result;
s
I guess
Copy code
var findResponse = this.findOne( query={ "_id": "mid:#mid#x" }, projection=projection );
		var result = isDefined("findResponse")?findResponse:{};
		application.utilities.debug( module="daoI4goV5.getMerchant", text="Find #mid#", data=result );
		return result;
will work. It'll just be confusing for future maintenance. LOL - same solution.
Hmmm, you use variables scope with structkey exists. I like.
👍 1
Final version for anyone following:
Copy code
var query = { "_id": "mid:#mid#" };
	var findResponse = this.findOne( query=query );
	// this structkeyexists() logic is required because at least with cf-2021, a findOne() returning "not found" wipes findResponse from existence
	var result = structKeyExists(local, "findResponse") ? findResponse : {};
	application.utilities.debug( module="daoI4goV5.getMerchant", text="Find #mid#", data={ query:query, result:result } );
	return result;
(edit: The original "variables" scope did not work, changing to "local" scope did the trick)
👍 1
❤️ 1