1

What I need is very simple, in SQL I would say I would merely need a SORT ASCENDING or DESCENDING.

But it has been a while I'm working with GraphQL, AppSync, DynamoDB and React-Native, and I still did not figure out how to sort my output list by name...

I'm using the simple scenario, without React-Native Apollo, just with the Connect component.

My Output list:

class PlantScreenNoApollo extends React.Component {

...

    render() {
       
        return (
    
    <View style={{flex:1, flexDirection:"column", justifyContent:"flex-start"}}>
        
        <View style={{flex:1,
                  flexDirection:"row",
                  justifyContent:"center",
        }}>
            <TextInput style={styles.sTextInput}
                        onChangeText={ (text) => this._updateFilter(text) }
                        value={this.state.filter}/>
            <Ionicons name={"ios-search"} size={30} />
        </View>

        <View style={{  flex:1, 
                        flexDirection:"column",
                        justifyContent:"flex-start",
                        alignContent: "center",
                        minHeight: "70%",}}>
                        
        <Connect query={ this.state.filter!=="" ? 
                         graphqlOperation(queries.listPlants, {
                            filter: {
                                name: {
                                    contains: this.state.filter
                                }
                            }
                         })
                         :
                         graphqlOperation(queries.listPlants)
                        
        }>
            {
                ( { data: { listPlants }, loading, error } ) => {
                    
                    if(error) return (<Text>Error</Text>);
                    
                    if(loading || !listPlants) return (<ActivityIndicator />);
                    
                    return (
                    
                          <FlatList
                            data={listPlants.items}
                            renderItem={({item}) => {
                                return (
                                    <View style={{borderBottomWidth:1, borderBottomColor:"green", padding:5}}>
                                    <TouchableOpacity onPress={()=>this._onPress(item)}>
                                        <View style={styles.hcontainer}>
                                            <Image source={{uri:this.state.logoURL}}
                                                style={styles.iconImage}
                                            />
                                            <View style={styles.vcontainer}>
                                                <Text style={styles.textH3}>{item.name}</Text>
                                                <View style={styles.hcontainerflexstart}>
                                                    { item.tea &&  <Image source={{uri:this.state.teaIconURL}} style={styles.iconImageSmall} />}
                                                    { item.bath &&  <Image source={{uri:this.state.bathIconURL}} style={styles.iconImageSmall} />}
                                                    { item.insence &&  <Image source={{uri:this.state.insenceIconURL}} style={styles.iconImageSmall} />}
                                                    { item.children &&  <Image source={{uri:this.state.childrenIconURL}} style={styles.iconImageSmall} />}
                                                </View>
                                            </View>
                                            <Text style={styles.textP}>{item.description.substr(0,50) + "(...)"}</Text>
                                        </View>
                                    </TouchableOpacity>    
                                    </View>
                                );
                            }}
                            keyExtractor={(item, index) => item.id}
                        />

                    );
                    
                    
                }
            }
        </Connect>
        </View>
        <View style={{flex:1, flexDirection:"column", justifyContent:"flex-start"}}>


...

        </View>
    </View>
      );  
    };
    
}

And this is my query description (auto-generated by the model + codegen)

export const listPlants = `query ListPlants(
  $filter: ModelPlantFilterInput
  $limit: Int
  $nextToken: String
) {
  listPlants(filter: $filter, limit: $limit, nextToken: $nextToken) {
    items {
      id
      name
      description
      ...
    }
    nextToken
  }
}

All I want is to sort the scan by name.

I tried even to create a secondary index, but it didn't change anything...

Does anyone know the best way to accomplish this?

rdrgtec
  • 592
  • 10
  • 26

1 Answers1

1

Change your listPlants resolver to perform a Query instead of a Scan and you can utilize the scanIndexForward boolean to determine if you want to return the results in ascending or descending order based on the index provided (in your case - 'name').

This will require you to index the name attribute in DynamoDB if it is not already.

For more information - look at the Query section in the following documentation:

In particular:

ScanIndexForward

Specifies the order for index traversal: If true (default), the traversal is performed in ascending order; if false, the traversal is performed in descending order.

Items with the same partition key value are stored in sorted order by sort key. If the sort key data type is Number, the results are stored in numeric order. For type String, the results are stored in order of UTF-8 bytes. For type Binary, DynamoDB treats each byte of the binary data as unsigned.

If ScanIndexForward is true, DynamoDB returns the results in the order in which they are stored (by sort key value). This is the default behavior. If ScanIndexForward is false, DynamoDB reads the results in reverse order by sort key value, and then returns the results to the client.

Here's a detailed stackoverflow answer that details this.

  • I'm trying to apply this solution, but I'm stumbling on $modelQueryExpression in my resolver - where does it come from? – rdrgtec Sep 11 '19 at 13:08
  • OK figured out that I had to #set the value on the resolver itself, and how to do it.. however I'm almost giving up using key conditions because in fact I need to pass nothing to the query expressions required, I just need all items sorted properly.... Thinking about creating a "container" table with a @connection which will generate a gsi - but I still don't know how to fill it properly... – rdrgtec Sep 11 '19 at 14:56