Firebase如何自动防止重复条目

1cklez4t  于 2023-02-05  发布在  其他
关注(0)|答案(5)|浏览(118)

我正在考虑使用firebase作为一个web应用程序的用户数据存储库,我目前的想法是使用用户加入时的时间戳作为引用该用户数据的键来存储每个用户的数据,这种方案的优点是它是一种为用户分配唯一整数id的简单方法,并且使用户的时间顺序排序变得简单。
然而,缺点是如果两个add user请求提交的数据相同,应用程序会很乐意添加两个单独的条目,这是不公平的。我可以把事情打乱(我开始认为我应该使用电子邮件作为关键,并根据连接数据而不是我当前的方案来确定优先级),但假设我不想这样做,有什么方法可以防止重复数据吗?
最简单的方法可能是这样做:

if(!searchFirebaseForUser(data)) {
    addUser(data);
}

但这绝对是一个竞态条件;两个请求很容易在数据库中同时查询和查找不到用户,并且同时添加。我想在事务中完成此操作,但Firebase事务支持似乎不支持此情况。有什么方法可以处理此问题吗?

8i9zcol2

8i9zcol21#

您可能必须使用用户名或电子邮件地址作为密钥,并尝试原子地写入该位置。
下面是transaction函数参考中的相关代码示例,在本例中,我们使用wilma作为用户的键。

// Try to create a user for wilma, but only if the user id 'wilma' isn't already taken.
var wilmaRef = new Firebase('https://SampleChat.firebaseIO-demo.com/users/wilma');
wilmaRef.transaction(function(currentData) {
  if (currentData === null) {
    return {name: {first: 'Wilma', last: 'Flintstone'} };
  } else {
    console.log('User wilma already exists.');
    return; // Abort the transaction.
  }
}, function(error, committed, snapshot) {
  if (error)
    console.log('Transaction failed abnormally!', error);
  else if (!committed)
    console.log('We aborted the transaction (because wilma already exists).');
  else
    console.log('User wilma added!');
  console.log('Wilma\'s data: ', snapshot.val());
});
ih99xse1

ih99xse12#

安全规则不足以强制唯一性吗?我不知道它们是否是原子的。

{
    "rules": {
        "users": {
            "$username": {
                ".write": "!data.exists()"
            }
        }
    }
}
x7rlezfr

x7rlezfr3#

您可以使用push自动生成按时间顺序递增的ID,这些ID不会与其他客户机冲突,即使它们是同时创建的(其中包含随机成分)。
例如:

var ref = new Firebase(URL);
var record = ref.push(userInfo);
console.log("User was assigned ID: " + record.name());
4urapxun

4urapxun4#

唯一可靠的解决方案应该由数据库核心提供。
我想唯一的解决办法是使用不同的数据库。或者使用node express编写自己的后端。

px9o7tmv

px9o7tmv5#

代替在fire-base数据库中定义规则,防止重复条目的最简单方法是首先从fire-base数据库中获取所有数据,并将其与您想要存储的数据(新数据)进行比较,如果与先前数据匹配,则再次放弃存储在数据库中,否则存储在数据库中。检查以下内容以获得更多清晰度。

public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private BroadcastReceiver mRegistrationBroadcastReceiver;
private TextView txtRegId, txtMessage;
DatabaseReference databaseArtists;
ListView listViewArtists;
public static String regId;
List<Artist> artistList;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
txtRegId = (TextView) findViewById(R.id.regid);
txtRegId.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            displayFirebaseRegId();
            boolean flag=false;
            String tokenId=regId;
            for(Artist a:artistList)
            {Log.d("RAaz",a.getTokenId()+"    "+tokenId);
                if(a.getTokenId().equalsIgnoreCase(tokenId))
                {
                    flag=true;
                    Toast.makeText(MainActivity.this, "True", Toast.LENGTH_SHORT).show();
                }
            }
            if(flag)
            {
                Toast.makeText(MainActivity.this, "User Already Exists", Toast.LENGTH_SHORT).show();
            }
            else {
                addArtist();
            }
        }
    });
    mRegistrationBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // checking for type intent filter
            if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
                // gcm successfully registered
                // now subscribe to `global` topic to receive app wide notifications
                FirebaseMessaging.getInstance().subscribeToTopic(Config.TOPIC_GLOBAL);
                displayFirebaseRegId();
            } else if (intent.getAction().equals(Config.PUSH_NOTIFICATION)) {
                // new push notification is received
                String message = intent.getStringExtra("message");
                Toast.makeText(getApplicationContext(), "Push notification: " + message, Toast.LENGTH_LONG).show();
                txtMessage.setText(message);
            }
        }
    };
    displayFirebaseRegId();
    databaseArtists = FirebaseDatabase.getInstance().getReference("artist");
    artistList = new ArrayList<>();}

下面的代码用于向firebase添加数据

private void addArtist() {
    String name = "User";
    String genre = regId;
    if (!TextUtils.isEmpty(name)) {
        String id = databaseArtists.push().getKey();
        Artist artist = new Artist(id,genre,name);
        databaseArtists.child(id).setValue(artist);
        Toast.makeText(this, "Artist Added", Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(this, "Please enter name", Toast.LENGTH_SHORT).show();
    }
}

使用onStart从firebase数据库获取详细信息

protected void onStart() {
    super.onStart();
    Toast.makeText(this, "On Start", Toast.LENGTH_SHORT).show();
    databaseArtists.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            artistList.clear();
            for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
                Artist artist = dataSnapshot1.getValue(Artist.class);
                artistList.add(artist);
            }
        }
        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    });
}

最后添加pojo类

public class Artist {
private String artistId;
private String tokenId;
private String roleName;

public Artist() {
}

public Artist(String artistId, String tokenId, String roleName) {
    this.artistId = artistId;
    this.tokenId = tokenId;
    this.roleName = roleName;
}

public String getArtistId() {
    return artistId;
}

public void setArtistId(String artistId) {
    this.artistId = artistId;
}

public String getTokenId() {
    return tokenId;
}

public void setTokenId(String tokenId) {
    this.tokenId = tokenId;
}

public String getRoleName() {
    return roleName;
}

public void setRoleName(String roleName) {
    this.roleName = roleName;
}

}

相关问题