I couldn't find much detail in the "official" documentation, but did come across this gist that illustrates many patterns.
The only "query by a specific id" pattern I could get to work is this one:
<apex:page >
<apex:remoteObjects>
<apex:remoteObjectModel name="Account" jsShorthand="Account" fields="Name,Id"/>
</apex:remoteObjects>
<script>
fetch = function(){
var a = new SObjectModel.Account();
a.retrieve({where: {Id: {eq: "001i000000cwvW9AAI"}}}, function(err, records){
if(err) alert(err.message);
else {
records.forEach(function(record) {
console.log(JSON.stringify(record));
});
}
});
};
</script>
<button onclick="fetch()">Fetch</button>
</apex:page>
which is like your first example except that it works... Your error message doesn't seem to reflect the "where" that you list; is it possible some other code is causing your error?
You can override the default remote object operations, programmatically get a count, add it to the result, and then use it in the Visualforce page.
In this case, to get the count you could override the retrieve
method to get a count of whatever you need and store it in a property. In the Visualforce callback you can access the property in the event.result
object. This isn’t an exact way to simulate the count()
but may work depending on the use case.
Here’s an example that overrides the Account’s retrieve and adds in a count of the number of Accounts owned by the current user.
Override in the Visualforce
The retrieve method is overridden by supplying the retrieve
attribute to the apex:remoteObjectModel
.
<apex:remoteObjectModel
jsShortHand="acct"
name="Account"
fields="Id,Name,Phone,Fax"
retrieve="{!$RemoteAction.AccountController.retrieveAccts}"/>
Override in the Apex Controller
public with sharing class AccountController {
@RemoteAction
public static Map<String, Object> retrieveAccts(
String type,
List<String> fields,
Map<String, Object> criteria
) {
// Retrieve using the standard retrieve
Map<String, Object> result = RemoteObjectController.retrieve(type, fields, criteria);
// Add in the total record count for the current user. Needed for pagination
Integer numOwnedAccts = [
SELECT Count()
FROM Account
WHERE OwnerId =: UserInfo.getUserId()
];
// Create a new map since the result map is read-only
Map<String, Object> customResult =
new Map<String, Object> {'totalRecordCount'=> numOwnedAccts};
customResult.putAll(result);
return customResult;
}
}
Using the Visualforce Remote Object
This code creates criteria to support pagination and then calls retrieve
. Note the line totalRecordCount = event.result.totalRecordCount
. That’s what gets back the count.
// Set up criteria for pagination
var criteria = {
limit: someLimitVal,
orderby: [ {Name: "ASC NULLS LAST"} ]
};
// If offset is zero there will be an error
if (offsetVal >= 1) {
criteria.offset = offsetVal;
}
var modelVar = new SObjectModel.acct();
modelVar.retrieve(criteria, function(err, records, event) {
if (err) {
console.log(err);
} else {
var totalRecordCount = event.result.totalRecordCount;
records.forEach(function(record) {
// do something
});
}
});
Unfortunately, you cannot get the non paged count of the criteria dynamically because the limit for limit
is 100. For example, it would be useful (but not currently possible) to be able to do something like the following in the override.
Map<String, Object> countCriteria = new Map<String, Object>(criteria);
countCriteria.remove('offset');
countCriteria.put(‘limit’, 2000);
Map<String, Object> countResult = RemoteObjectController.retrieve(type, fields, countCriteria);
Integer totalRecordCount = (Integer) countResult.get('size');
Best Answer
OPTION 1: Nested logical constructions to prevent the clash of identifiers
Caution: it seems to be important, that all ors and ands have at least two nodes. So if necessary, you have to add fake-conditions which evaluate neutrally to your needs.
OPTION 2: Add the Model fields twice (not verified)