0

I have a realm database synced up. The database contains multiple products having categories and company name. Some products have same company name, some products have same category name and some products have everything same except id. What I need to do is make a browse component where the user can browse for company name. I created an autocomplete search. The search should autocomplete the company name show categories of products in the screen. What I am facing right now is the autocomplete search shows same company name multiple times (for each product in the database). Also I need to render the categories having same name only one time.

Browse screen

Here's my database schema:

import Realm from 'realm';
import axios from 'axios';

class Product extends Realm.Object {}
Product.schema = {
  name: 'Product',
  properties: {
    cname: 'string',
    pname: 'string',
    id: 'int',
    price: 'string',
    code: 'string',
    category: 'string',
  },
  primaryKey: 'id',
};

let getAllProducts = () => {
  return realm.objects('Product');
};
export {getAllProducts}

Browse Screen:

import React, {useEffect, useState} from 'react';
import {
  StyleSheet,
  View,
  SafeAreaView,
  Text,
  FlatList,
  TouchableWithoutFeedback,
  Alert,
} from 'react-native';
import {Searchbar, RadioButton} from 'react-native-paper';
import {
  ApplicationProvider,
  Button,
  Icon,
  IconRegistry,
  Layout,
  Card,
} from '@ui-kitten/components';
import {EvaIconsPack} from '@ui-kitten/eva-icons';
import * as eva from '@eva-design/eva';
import {getAllProducts, addProduct, deleteAllProduct} from '../database/realm';
import {Autocomplete, AutocompleteItem} from '@ui-kitten/components';
import TextTicker from 'react-native-text-ticker';

const filter = (item, query) =>
  item.cname.toLowerCase().includes(query.toLowerCase());

const StarIcon = props => <Icon {...props} name="star" />;

export default function browse() {
  const [value, setValue] = React.useState(null);
  const [data, setData] = React.useState(getAllProducts());
  const onSelect = index => {
    setValue(data[index].cname);
  };
  const onChangeText = query => {
    setValue(query);
    setData(getAllProducts().filter(item => filter(item, query)));
  };
  const clearInput = () => {
    setValue('');
    setData(getAllProducts());
  };
  const renderOption = (item, index) => (
    <AutocompleteItem key={index} title={item.cname} />
  );
  const renderCloseIcon = props => (
    <TouchableWithoutFeedback onPress={clearInput}>
      <Icon {...props} name="close" />
    </TouchableWithoutFeedback>
  );

  useEffect(() => {
    console.log('company selected:', value);
  });

  function CnameValue() {
    return getAllProducts().filtered('cname == $0', value);
  }
  return (
    <SafeAreaView>
      <Autocomplete
        placeholder="Type company name"
        value={value}
        accessoryRight={renderCloseIcon}
        onChangeText={onChangeText}
        onSelect={onSelect}>
        {data.map(renderOption)}
      </Autocomplete>
    </SafeAreaView>
  );
}
6
  • 1
    I would suggest having another realm object Company that is a unique list of companies the user can select from when creating the Products. This line return realm.objects('Product'); will return every single product which could be a LOT of data. Filtering that initially will really improve performance and make the returned results more manageable. Commented Sep 6, 2021 at 17:43
  • I understand this idea. Thank you Commented Sep 8, 2021 at 8:00
  • Hi again, Im stuck at populating my another realm object Company with unique list of companies. I have to use api to store list of companies. How do I avoid duplicating the company name? Commented Sep 10, 2021 at 10:29
  • You can easily check to see if it exists before writing - should just be a couple lines of code. Commented Sep 10, 2021 at 16:31
  • 1
    While that may work for now, it's not scaleable. When a Realm Results object is 'converted' to an array, the memory friendly lazily loaded objects are not longer lazy; they are ALL loaded into memory which could overwhelm the device for larger datasets. It would be easy and safe to just perform a query on Realm for the company name in question and if it doesn't exist, allow it to be created. That's going to protect the devices memory and be scaleable. Commented Sep 12, 2021 at 12:48

1 Answer 1

0

I think what you are searching for is the DISTINCT filter. In your example it would be something like

getAllProducts().filtered('cname == $0 DISTINCT(cname)', value);

The documentation is currently available here:

https://docs.mongodb.com/realm-legacy/docs/javascript/latest/#filtering

the relevant part is: Sorting and find distinct values are possible with functions SORT and DISTINCT, e.g. age > 20 SORT(name ASC, age DESC) DISTINCT(name).

Sign up to request clarification or add additional context in comments.

5 Comments

Its still showing 38 parryware in autocomplete search option. I have 38 products in my database where all the products have company name "parryware". I want to show parryware only 1 time in autocomplete search options.
I think you're going the right direction with this answer but is that a Realm filter? And what about case and diacritic insensitive ([cd])?
this function is according to the last documentation of realm-js. In other versions of the Framework distinct is a separate method.
I think the OP and future readers would benefit from a link to that documentation - can you add one to your answer?
done that and for future availability (broken link) also the relevant part

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.