集 - React Native SDK
realm@10.5.0
版本中的新增功能。
Realm集是一种特殊对象,允许您存储唯一值的集合。 Realm集基于JavaScript 集 ,但只能包含单一类型的值,并且只能在写事务(write transaction)中修改。 Set 允许您执行数学运算,例如查找两个 Set 之间的并集、交集或差值。要学习;了解有关执行这些操作的更多信息,请参阅 MDN 文档中的“ 实施基本设立操作”。
Realm 对象模型
您可以通过两种方式将 Realm 对象模型属性类型定义为 Realm 集:
指定 Set 将包含的数据类型,紧接着是
<>
。对于更复杂的属性,请使用对象符号和
type
字段。
1 class Character extends Realm.Object { 2 static schema = { 3 name: 'Character', 4 primaryKey: '_id', 5 properties: { 6 _id: 'objectId', 7 name: 'string', 8 levelsCompleted: 'int<>', 9 inventory: { 10 type: 'set', 11 objectType: 'string', 12 }, 13 }, 14 }; 15 }
1 class Character extends Realm.Object<Character> { 2 _id!: Realm.BSON.ObjectId; 3 name!: string; 4 levelsCompleted!: Realm.Set<number>; 5 inventory!: Realm.Set<string>; 6 7 static schema: ObjectSchema = { 8 name: 'Character', 9 primaryKey: '_id', 10 properties: { 11 _id: 'objectId', 12 name: 'string', 13 levelsCompleted: 'int<>', 14 inventory: { 15 type: 'set', 16 objectType: 'string', 17 }, 18 }, 19 }; 20 }
使用集合创建对象
要创建具有 Realm 集属性的对象,您必须在写事务中创建该对象。定义 Realm 对象时,通过传递空数组或具有初始值的数组来初始化 Realm 集。
例子
在以下CreateInitialCharacters
组件示例中,我们创建具有 Set 属性的Character
对象。
CreateInitialCharacters
组件将执行以下操作:
通过调用该组件中的
useRealm()
钩子来访问打开的 Realm 实例。使用 React 的 useEffect
useEffect
钩子,使用 和空依赖数组仅调用匿名函数一次。在匿名函数中,我们在写事务中创建了两个不同的Character
对象。 我们将每个字符的inventory
和levelsCompleted
集设置为具有初始值的数组。通过将
Character
类传递给useQuery()
钩子,检索 Realm 实例中的所有字符。在用户界面中将每个字符的名字显示为
Text
元素。
1 const CreateInitialCharacters = () => { 2 const realm = useRealm(); 3 useEffect(() => { 4 realm.write(() => { 5 realm.create('Character', { 6 _id: new Realm.BSON.ObjectId(), 7 name: 'AdventurousPlayer', 8 inventory: ['elixir', 'compass', 'glowing shield'], 9 levelsCompleted: [4, 9], 10 }); 11 }); 12 realm.write(() => { 13 realm.create('Character', { 14 _id: new Realm.BSON.ObjectId(), 15 name: 'HealerPlayer', 16 inventory: ['estus flask', 'gloves', 'rune'], 17 levelsCompleted: [1, 2, 5, 24], 18 }); 19 }); 20 }, []); 21 const characters = useQuery(Character); 22 23 return ( 24 <View> 25 {characters.map(character => ( 26 <View key={character._id}> 27 <Text>{character.name}</Text> 28 </View> 29 ))} 30 </View> 31 ); 32 };
1 const CreateInitialCharacters = () => { 2 const realm = useRealm(); 3 useEffect(() => { 4 realm.write(() => { 5 realm.create('Character', { 6 _id: new Realm.BSON.ObjectId(), 7 name: 'AdventurousPlayer', 8 inventory: ['elixir', 'compass', 'glowing shield'], 9 levelsCompleted: [4, 9], 10 }); 11 }); 12 13 realm.write(() => { 14 realm.create('Character', { 15 _id: new Realm.BSON.ObjectId(), 16 name: 'HealerPlayer', 17 inventory: ['estus flask', 'gloves', 'rune'], 18 levelsCompleted: [1, 2, 5, 24], 19 }); 20 }); 21 }, []); 22 const characters = useQuery(Character); 23 24 return ( 25 <View> 26 {characters.map(character => ( 27 <View key={character._id}> 28 <Text>{character.name}</Text> 29 </View> 30 ))} 31 </View> 32 ); 33 };
将项目添加到 Set 中
要将列项添加到集中,请将新值传递给写事务中的 Realm.Set.add() 方法。
例子
在以下 AddInventoryToCharacter
组件示例中,我们将新的集元素添加到字符库存。
AddInventoryToCharacter
组件将执行以下操作:
通过调用该组件中的
useRealm()
钩子来访问打开的 Realm 实例。创建称为“inventoryItem”的状态变量,表示要向库存集添加的新库存项目。
通过将
Character
类传递给useQuery()
钩子并运行Collection.filtered()来检索字符 方法,用于筛选名称与 属性匹配的 字符characterName
。然后,我们将变量character
设置为第一个匹配结果。创建用于执行写事务的组件方法
addInventoryItem()
,写事务通过将inventoryItem
状态变量传递到Realm.Set.add()
来将库存项目添加至字符库存中。呈现更改
inventoryItem
状态变量的TextInput
和调用addInventoryItem()
方法的Button
。
1 const AddInventoryToCharacter = ({characterName}) => { 2 const realm = useRealm(); 3 const [inventoryItem, setInventoryItem] = useState(''); 4 const character = useQuery( 5 Character, 6 characters => { 7 return characters.filtered(`name = '${characterName}'`); 8 }, 9 [characterName], 10 )[0]; 11 12 const addInventoryItem = () => { 13 realm.write(() => { 14 character?.inventory.add(inventoryItem); 15 }); 16 }; 17 18 return ( 19 <View> 20 <TextInput 21 onChangeText={text => setInventoryItem(text)} 22 value={inventoryItem} 23 /> 24 <Button 25 title='Add Inventory Item' 26 onPress={addInventoryItem} 27 /> 28 </View> 29 ); 30 };
1 const AddInventoryToCharacter = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const realm = useRealm(); 7 const [inventoryItem, setInventoryItem] = useState(''); 8 const character = useQuery( 9 Character, 10 characters => { 11 return characters.filtered(`name = '${characterName}'`); 12 }, 13 [characterName], 14 )[0]; 15 16 const addInventoryItem = () => { 17 realm.write(() => { 18 character?.inventory.add(inventoryItem); 19 }); 20 }; 21 22 return ( 23 <View> 24 <TextInput 25 onChangeText={text => setInventoryItem(text)} 26 value={inventoryItem} 27 /> 28 <Button 29 title='Add Inventory Item' 30 onPress={addInventoryItem} 31 /> 32 </View> 33 ); 34 };
检查集是否有特定项并检查集的大小
您可能需要检查有关您的 Set 的信息,例如其大小或是否包含特定项目。
要确定 Set 是否包含特定值,请将该值传递给Realm.Set.has() 方法。 如果集包含指定的值,则此方法将返回true
。
要了解集有多少列项,您可以检查其 size
属性。
例子
在以下QueryCharacterInventory
组件的示例中,我们检查字符的库存大小以及它是否具有特定项目。
QueryCharacterInventory
组件将执行以下操作:
创建称为“inventoryItem”的状态变量,表示您要在字符库存中搜索的库存项目。
使用
useQuery
钩子对所有字符执行查询,并过滤结果以仅包括名称与作为 prop 传递给组件的characterName
相匹配的字符。然后,我们得到第一个匹配结果。通过将
Character
类传递给useQuery()
钩子并运行Collection.filtered()来检索字符 方法,用于筛选名称与characterName
属性匹配的字符。 然后,我们将变量character
设置为第一个匹配结果。创建一个组件方法
queryCharacterInventory
,将inventoryItem
状态变量传递给Realm.Set.has()
,以检查字符库存中是否包含该项目。 如果字符库存中包含该项目,则该方法会提醒该字符拥有该项目。如果字符库存中不包含该项目,则该方法会提醒该字符没有该项目。呈现字符名称,并使用字符库存的
size
属性呈现库存大小。 它还呈现一个用于更改inventoryItem
状态变量的TextInput
,以及一个调用queryCharacterInventory
方法的Button
。
1 const QueryCharacterInventory = ({characterName}) => { 2 const [inventoryItem, setInventoryItem] = useState(''); 3 const character = useQuery( 4 Character, 5 characters => { 6 return characters.filtered(`name = '${characterName}'`); 7 }, 8 [characterName], 9 )[0]; 10 11 const queryCharacterInventory = () => { 12 const characterDoesHaveItem = character.inventory.has(inventoryItem); 13 if (characterDoesHaveItem) { 14 Alert.alert(`Character has item: ${inventoryItem}`); 15 } else { 16 Alert.alert(`Item not found in character's inventory`); 17 } 18 }; 19 return ( 20 <View> 21 <Text>{character.name}</Text> 22 <Text> 23 Total number of inventory items: {character.inventory.size} 24 </Text> 25 <TextInput 26 onChangeText={text => setInventoryItem(text)} 27 value={inventoryItem} 28 /> 29 <Button 30 title='Query for Inventory' 31 onPress={queryCharacterInventory} 32 /> 33 </View> 34 ); 35 };
1 const QueryCharacterInventory = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const [inventoryItem, setInventoryItem] = useState(''); 7 const character = useQuery( 8 Character, 9 characters => { 10 return characters.filtered(`name = '${characterName}'`); 11 }, 12 [characterName], 13 )[0]; 14 15 const queryCharacterInventory = () => { 16 const characterDoesHaveItem: Boolean = 17 character.inventory.has(inventoryItem); 18 if (characterDoesHaveItem) { 19 Alert.alert(`Character has item: ${inventoryItem}`); 20 } else { 21 Alert.alert(`Item not found in character's inventory`); 22 } 23 }; 24 return ( 25 <View> 26 <Text>{character.name}</Text> 27 <Text> 28 Total number of inventory items: {character.inventory.size} 29 </Text> 30 <TextInput 31 onChangeText={text => setInventoryItem(text)} 32 value={inventoryItem} 33 /> 34 <Button 35 title='Query for Inventory' 36 onPress={queryCharacterInventory} 37 /> 38 </View> 39 ); 40 };
删除 Set 信息
您可能想要从 Set 中删除特定项目或所有项目。
要从集中删除特定值,请将该值传递给写事务中的 Realm.Set.delete() 方法。
要清除集,请运行写事务中的 Realm.Set.clear() 方法。
例子
在以下 RemoveInventoryFromCharacter
组件示例中,我们从集中删除了特定项目并清除了集中的所有项目。
RemoveInventoryFromCharacter
组件将执行以下操作:
通过调用该组件中的
useRealm()
钩子来访问打开的 Realm 实例。创建称为“inventoryItem”的状态变量,表示要从库存 Set 中删除的库存项目。
创建一个组件方法
removeInventoryItem
,将inventoryItem
状态变量传递给Realm.Set.delete()
,以从字符库存中删除该项目。创建组件方法
removeAllInventory
,该方法调用Realm.Set.clear()
,从字符库存删除所有列项。呈现一个用于更改
inventoryItem
状态变量的TextInput
,以及两个分别调用removeInventoryItem
和removeAllInventory
方法的Button
组件。
1 const RemoveInventoryFromCharacter = ({characterName}) => { 2 const realm = useRealm(); 3 const [inventoryItem, setInventoryItem] = useState(''); 4 const character = useQuery( 5 Character, 6 characters => { 7 return characters.filtered(`name = '${characterName}'`); 8 }, 9 [characterName], 10 )[0]; 11 12 const removeInventoryItem = () => { 13 realm.write(() => { 14 character?.inventory.delete(inventoryItem); 15 }); 16 }; 17 const removeAllInventory = () => { 18 realm.write(() => { 19 character?.inventory.clear(); 20 }); 21 }; 22 return ( 23 <View> 24 <Text>{character.name}</Text> 25 <TextInput 26 onChangeText={text => setInventoryItem(text)} 27 value={inventoryItem} 28 /> 29 <Button 30 title='Remove Inventory Item' 31 onPress={removeInventoryItem} 32 /> 33 <Button 34 title='Remove All Inventory' 35 onPress={removeAllInventory} 36 /> 37 </View> 38 ); 39 };
1 const RemoveInventoryFromCharacter = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const realm = useRealm(); 7 const [inventoryItem, setInventoryItem] = useState(''); 8 const character = useQuery( 9 Character, 10 characters => { 11 return characters.filtered(`name = '${characterName}'`); 12 }, 13 [characterName], 14 )[0]; 15 16 const removeInventoryItem = () => { 17 realm.write(() => { 18 character?.inventory.delete(inventoryItem); 19 }); 20 }; 21 const removeAllInventory = () => { 22 realm.write(() => { 23 character?.inventory.clear(); 24 }); 25 }; 26 return ( 27 <View> 28 <Text>{character.name}</Text> 29 <TextInput 30 onChangeText={text => setInventoryItem(text)} 31 value={inventoryItem} 32 /> 33 <Button 34 title='Remove Inventory Item' 35 onPress={removeInventoryItem} 36 /> 37 <Button 38 title='Remove All Inventory' 39 onPress={removeAllInventory} 40 /> 41 </View> 42 ); 43 };
遍历集
您可以遍历集合以访问集合中的每个项目。 要遍历集,请使用Set.map()
方法或替代 迭代方法。
但是,默认情况下,不保证集中项目的顺序。 要按顺序遍历集合,可以将集合的项目存储在 状态变量 中 并在向集合添加新项时更新该状态变量。
例子
在以下 TraverseCharacterInventory
组件示例中,字符开始时没有库存列项。当用户将列项添加到库存集中时,该组件将以有序和无序列表的形式显示集中的每个列项。
TraverseCharacterInventory
组件将执行以下操作:
通过调用该组件中的
useRealm()
钩子来访问打开的 Realm 实例。创建一个名为“inventoryItem”的状态变量,表示要添加到库存集中的新库存项目。
创建一个名为"inventory"的状态变量,将按插入顺序保存字符的库存项目。
通过将
Character
类传递给useQuery()
钩子并运行Collection.filtered()来检索字符 方法,用于筛选名称与 属性匹配的 字符characterName
。然后,我们将变量character
设置为第一个匹配结果。创建用于执行写事务的组件方法
addInventoryItem()
,该写事务通过将inventoryItem
状态变量传递给Realm.Set.add()来将库存项目添加到字符的库存中。 方法。 写事务完成后,该方法将inventoryItem
添加到inventory
数组状态变量。呈现更改
inventoryItem
状态变量的TextInput
和调用addInventoryItem()
方法的Button
。通过遍历
inventory
数组状态变量,按照添加到集中的顺序呈现字符的库存列项的列表。通过遍历
character.inventory
呈现字符库存的无序列表。
1 const TraverseCharacterInventory = ({characterName}) => { 2 const realm = useRealm(); 3 const [inventoryItem, setInventoryItem] = useState(''); 4 const [inventory, setInventory] = useState([]); 5 6 const character = useQuery( 7 Character, 8 characters => { 9 return characters.filtered(`name = '${characterName}'`); 10 }, 11 [characterName], 12 )[0]; 13 14 const addInventoryItem = () => { 15 realm.write(() => { 16 character?.inventory.add(inventoryItem); 17 }); 18 setInventory([...inventory, inventoryItem]); 19 }; 20 21 return ( 22 <View> 23 <Text>{character.name}</Text> 24 <Text>Add an item to the inventory:</Text> 25 <TextInput 26 onChangeText={text => setInventoryItem(text)} 27 value={inventoryItem} 28 /> 29 <Button 30 title='Add Inventory Item' 31 onPress={addInventoryItem} 32 /> 33 34 <Text>Ordered Inventory:</Text> 35 {inventory.map(item => ( 36 <Text>{item}</Text> 37 ))} 38 39 <Text>Unordered Inventory:</Text> 40 {character.inventory.map(item => ( 41 <Text>{item}</Text> 42 ))} 43 </View> 44 ); 45 };
1 const TraverseCharacterInventory = ({ 2 characterName, 3 }: { 4 characterName: string; 5 }) => { 6 const realm = useRealm(); 7 const [inventoryItem, setInventoryItem] = useState<string>(''); 8 const [inventory, setInventory] = useState<string[]>([]); 9 10 const character = useQuery( 11 Character, 12 characters => { 13 return characters.filtered(`name = '${characterName}'`); 14 }, 15 [characterName], 16 )[0]; 17 18 const addInventoryItem = () => { 19 realm.write(() => { 20 character?.inventory.add(inventoryItem); 21 }); 22 setInventory([...inventory, inventoryItem]); 23 }; 24 25 return ( 26 <View> 27 <Text>{character.name}</Text> 28 <Text>Add an item to the inventory:</Text> 29 <TextInput 30 onChangeText={text => setInventoryItem(text)} 31 value={inventoryItem} 32 /> 33 <Button 34 title='Add Inventory Item' 35 onPress={addInventoryItem} 36 /> 37 38 <Text>Ordered Inventory:</Text> 39 {inventory.map(item => ( 40 <Text>{item}</Text> 41 ))} 42 43 <Text>Unordered Inventory:</Text> 44 {character.inventory.map(item => ( 45 <Text>{item}</Text> 46 ))} 47 </View> 48 ); 49 };